diff --git a/android/src/main/java/it/innove/BleManager.java b/android/src/main/java/it/innove/BleManager.java index e531cc37..26fa504b 100644 --- a/android/src/main/java/it/innove/BleManager.java +++ b/android/src/main/java/it/innove/BleManager.java @@ -767,6 +767,8 @@ private void disconnectPeripherals() { if (peripheral.isConnected()) { peripheral.disconnect(null, true); } + peripheral.errorAndClearAllCallbacks("disconnected by BleManager"); + peripheral.resetQueuesAndBuffers(); } } } diff --git a/android/src/main/java/it/innove/DefaultScanManager.java b/android/src/main/java/it/innove/DefaultScanManager.java index b8205f87..d6c2ed89 100644 --- a/android/src/main/java/it/innove/DefaultScanManager.java +++ b/android/src/main/java/it/innove/DefaultScanManager.java @@ -7,6 +7,8 @@ import android.annotation.SuppressLint; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; @@ -45,7 +47,9 @@ public void stopScan(Callback callback) { // update scanSessionId to prevent stopping next scan by running timeout thread scanSessionId.incrementAndGet(); - getBluetoothAdapter().getBluetoothLeScanner().stopScan(mScanCallback); + final BluetoothLeScanner scanner = getBluetoothAdapter().getBluetoothLeScanner(); + if (scanner != null) + scanner.stopScan(mScanCallback); isScanning = false; callback.invoke(); } @@ -173,7 +177,8 @@ public void run() { // check current scan session was not stopped if (scanSessionId.intValue() == currentScanSession) { if (btAdapter.getState() == BluetoothAdapter.STATE_ON) { - btAdapter.getBluetoothLeScanner().stopScan(mScanCallback); + final BluetoothLeScanner scanner = btAdapter.getBluetoothLeScanner(); + if (scanner != null) scanner.stopScan(mScanCallback); isScanning = false; } diff --git a/android/src/main/java/it/innove/Peripheral.java b/android/src/main/java/it/innove/Peripheral.java index fad93cea..12332ebd 100644 --- a/android/src/main/java/it/innove/Peripheral.java +++ b/android/src/main/java/it/innove/Peripheral.java @@ -12,6 +12,7 @@ import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; + import android.content.Context; import android.os.Build; import android.os.Handler; @@ -160,14 +161,9 @@ public void connect(final Callback callback, Activity activity, ReadableMap opti public void disconnect(final Callback callback, final boolean force) { mainHandler.post(() -> { - for (Callback connectCallback : connectCallbacks) { - connectCallback.invoke("Disconnect called before connect callback invoked"); - } - connectCallbacks.clear(); + errorAndClearAllCallbacks("Disconnect called before the command completed"); + resetQueuesAndBuffers(); connected = false; - clearBuffers(); - commandQueue.clear(); - commandQueueBusy = false; if (gatt != null) { try { @@ -297,15 +293,83 @@ public BluetoothDevice getDevice() { public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); mainHandler.post(() -> { - for (Callback retrieveServicesCallback : retrieveServicesCallbacks) { - WritableMap map = this.asWritableMap(gatt); - retrieveServicesCallback.invoke(null, map); + if (gatt == null) { + for (Callback retrieveServicesCallback : retrieveServicesCallbacks) { + retrieveServicesCallback.invoke("Error during service retrieval: gatt is null"); + } + } + else if (status == BluetoothGatt.GATT_SUCCESS) + { + for (Callback retrieveServicesCallback : retrieveServicesCallbacks) { + WritableMap map = this.asWritableMap(gatt); + retrieveServicesCallback.invoke(null, map); + } + } + else { + for (Callback retrieveServicesCallback : retrieveServicesCallbacks) { + retrieveServicesCallback.invoke("Error during service retrieval."); + } } retrieveServicesCallbacks.clear(); completedCommand(); }); } + public void errorAndClearAllCallbacks(final String errorMessage) { + + for (Callback writeCallback : writeCallbacks) { + writeCallback.invoke(errorMessage); + } + writeCallbacks.clear(); + + for (Callback retrieveServicesCallback : retrieveServicesCallbacks) { + retrieveServicesCallback.invoke(errorMessage); + } + retrieveServicesCallbacks.clear(); + + for (Callback readRSSICallback : readRSSICallbacks) { + readRSSICallback.invoke(errorMessage); + } + readRSSICallbacks.clear(); + + for (Callback registerNotifyCallback : registerNotifyCallbacks) { + registerNotifyCallback.invoke(errorMessage); + } + registerNotifyCallbacks.clear(); + + for (Callback requestMTUCallback : requestMTUCallbacks) { + requestMTUCallback.invoke(errorMessage); + } + requestMTUCallbacks.clear(); + + for (Callback readCallback : readCallbacks) { + readCallback.invoke(errorMessage); + } + readCallbacks.clear(); + + for (Callback readDescriptorCallback : readDescriptorCallbacks) { + readDescriptorCallback.invoke(errorMessage); + } + readDescriptorCallbacks.clear(); + + for (Callback callback : writeDescriptorCallbacks) { + callback.invoke(errorMessage); + } + writeDescriptorCallbacks.clear(); + + for (Callback connectCallback : connectCallbacks) { + connectCallback.invoke(errorMessage); + } + connectCallbacks.clear(); + } + + public void resetQueuesAndBuffers() { + writeQueue.clear(); + commandQueue.clear(); + commandQueueBusy = false; + connected = false; + clearBuffers(); + } @Override public void onConnectionStateChange(BluetoothGatt gatta, int status, final int newState) { @@ -315,7 +379,7 @@ public void onConnectionStateChange(BluetoothGatt gatta, int status, final int n mainHandler.post(() -> { gatt = gatta; - if (status != BluetoothGatt.GATT_SUCCESS) { + if (gatt != null && status != BluetoothGatt.GATT_SUCCESS) { gatt.close(); } @@ -333,59 +397,13 @@ public void onConnectionStateChange(BluetoothGatt gatta, int status, final int n } else if (newState == BluetoothProfile.STATE_DISCONNECTED || status != BluetoothGatt.GATT_SUCCESS) { - for (Callback writeCallback : writeCallbacks) { - writeCallback.invoke("Device disconnected"); - } - writeCallbacks.clear(); - - for (Callback retrieveServicesCallback : retrieveServicesCallbacks) { - retrieveServicesCallback.invoke("Device disconnected"); - } - retrieveServicesCallbacks.clear(); - - for (Callback readRSSICallback : readRSSICallbacks) { - readRSSICallback.invoke("Device disconnected"); - } - readRSSICallbacks.clear(); - - for (Callback registerNotifyCallback : registerNotifyCallbacks) { - registerNotifyCallback.invoke("Device disconnected"); - } - registerNotifyCallbacks.clear(); - - for (Callback requestMTUCallback : requestMTUCallbacks) { - requestMTUCallback.invoke("Device disconnected"); - } - requestMTUCallbacks.clear(); - - for (Callback readCallback : readCallbacks) { - readCallback.invoke("Device disconnected"); - } - readCallbacks.clear(); - - for (Callback readDescriptorCallback : readDescriptorCallbacks) { - readDescriptorCallback.invoke("Device disconnected"); - } - readDescriptorCallbacks.clear(); - - for (Callback callback : writeDescriptorCallbacks) { - callback.invoke("Device disconnected"); - } - writeDescriptorCallbacks.clear(); - - for (Callback connectCallback : connectCallbacks) { - connectCallback.invoke("Connection error"); + errorAndClearAllCallbacks("Device disconnected"); + resetQueuesAndBuffers(); + if (gatt != null) { + gatt.disconnect(); + gatt.close(); } - connectCallbacks.clear(); - writeQueue.clear(); - commandQueue.clear(); - commandQueueBusy = false; - connected = false; - clearBuffers(); - - gatt.disconnect(); - gatt.close(); gatt = null; sendDisconnectionEvent(device, BluetoothGatt.GATT_SUCCESS); } @@ -891,7 +909,9 @@ private byte[] copyOf(byte[] source) { } private boolean enqueue(Runnable command) { + final boolean result = commandQueue.add(command); + if (result) { nextCommand(); } else { @@ -921,9 +941,9 @@ private void nextCommand() { // Check if we still have a valid gatt object if (gatt == null) { - Log.d(BleManager.LOG_TAG, "Error, gatt is null"); - commandQueue.clear(); - commandQueueBusy = false; + Log.d(BleManager.LOG_TAG, "Error, gatt is null. Fill all callbacks with an error"); + errorAndClearAllCallbacks("Gatt is null"); + resetQueuesAndBuffers(); return; } @@ -971,6 +991,10 @@ public void readRSSI(final Callback callback) { public void refreshCache(Callback callback) { enqueue(() -> { try { + if (gatt == null) { + throw new Exception("gatt is null"); + } + Method localMethod = gatt.getClass().getMethod("refresh", new Class[0]); boolean res = (Boolean) localMethod.invoke(gatt, new Object[0]); callback.invoke(null, res); @@ -1218,6 +1242,9 @@ private BluetoothGattCharacteristic findWritableCharacteristic(BluetoothGattServ writeProperty = BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE; } + if (service == null) { + throw new Exception("Service is null."); + } List characteristics = service.getCharacteristics(); for (BluetoothGattCharacteristic characteristic : characteristics) { if ((characteristic.getProperties() & writeProperty) != 0