NordicSemiconductor / Android-BLE-Library

A library that makes working with Bluetooth LE on Android a pleasure. Seriously.
BSD 3-Clause "New" or "Revised" License
1.98k stars 413 forks source link

Issue with disconnect question #569

Open smileklvens opened 1 month ago

smileklvens commented 1 month ago

Environment no.nordicsemi.android:ble:2.7.5 Mobile phone: Huawei P30, Redmi Note 7

I have bound multiple Bluetooth devices and switched between them in the list. To ensure that only one can be connected at the same time, I disconnected one and then linked the other. When calling the disconnect method, I found two occasional issues

  1. Callback to the done method, but the Bluetooth device is still connected, meaning it is not disconnected
  2. Occasionally do not callback. do, fail, then methods

The calling code is as follows:

BleManager. disconnect()
   .timeout(5_000)
   .done(device -> {
      Log. e ("BluetoothWrapper", "successfully disconnected, status:"+bluetoolWrapper. isConnectied());
   })
   .fail((device, status) -> {
      Log. e ("Bluetooth Wrapper", "Disconnect failed");
   })
   .then(device -> {
      Log.e("BluetoothWrapper", "disconnect,then");
   })
   .enqueue();

Search found an article https://www.jianshu.com/p/7268084cb5f6 I don't know right or wrong, but I haven't solved it yet Please help me, thank you

smileklvens commented 1 month ago

To add: When the device is disconnected immediately after it is connected, there may be no callback situation. When printing the log, it is found that the initialization method should be used again. The pseudocode is as follows:

super.initialize();
beginAtomicRequestQueue()
   .add(enableNotifications(mBatteryLevelChar))
   .add(enableNotifications(mChargeChar))
   .add(enableNotifications(mControlNotifyChar))
   .add(enableNotifications(mWriteNotifyChar))
   .add(enableNotifications(mControlChar))
   .enqueue();
// Electricity level
setNotificationCallback(mBatteryLevelChar)
   .with((device, data) -> {
      ...
   });
// Version number
readDeviceVersion(mFirwareRevisionChar);
// Reading battery level
readBattery();
// Synchronize UTC
syncUtc();
// Compatible with hardware code, requesting high priority connections and setting MTU
mHandler.postDelayed(() -> {         
   requestConnectionPriority(ConnectionPriorityRequest. CONNECTION_PRIORITY_BALANCED)
      .enqueue();
   requestMtu(128)
      .enqueue();
}, 10_000);
philips77 commented 1 month ago

Callback to the done method, but the Bluetooth device is still connected, meaning it is not disconnected

Both Android and iOS allow "connecting" to the same physical device from multiple BluetoothGatt (or CBPeripheral) objects. You may call device.connectGatt(...) multiple times in your app, but also other apps may connect to it. It is only when the last such object gets disconnected that the system terminates the physical link to the remote device. The system may give up to a second for other apps to claim the connection back.

To force disconnection from your app you need to implement a GATT command, e.g. an Op Code, that you write to some Control Point characteristic to trigger disconnection initiated from the remote side (or a reset). This will cause all the clients to receive disconnection event.

philips77 commented 1 month ago

Occasionally do not callback. do, fail, then methods

There's also invalid callback, when the request could not be executed for some reason. Perhaps that one gets called? If you don't get any of them, this looks like a bug. Could you provide logs, which you get from the log(..) method in the BleManager class?

philips77 commented 1 hour ago

Hello, Did you find a solution to the issue?