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.99k stars 414 forks source link

after bonding, then call writeCharacteristic, it fail #498

Open eaglewangy opened 1 year ago

eaglewangy commented 1 year ago

I use a wrong email in the commit for #479. Now re-commit using the correct email address for CLA @philips77 . Please review and merge to main branch

eaglewangy commented 1 year ago

@philips77 Is there an ETA?

philips77 commented 1 year ago

The issue with your proposal is that it may work for you case but we have to test it on different Android versions. According to our knowledge, if one for example call read characteristic which would initiate bonding some Android versions will repeat the request automatically after bonding is successful. Therefore this return; there. The onCharacteristicRead callback would be called with the value and only then the queue would be resumed.

As you see few lines above, for Android versions lower than Oreo we do call break; if there's a ongoing request. We have not test it for some time now. Google is really good in changing these things without any information.

philips77 commented 1 year ago

But I agree, if you're using ensureBond() the code should look more like that:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
   if (request != null) {
    // Repeat the last command in that case.
    enqueueFirst(request);
    break;
   }
}
if (request != null) {
   // Request should be repeated automatically.
   return;
}
break;
philips77 commented 1 year ago

Also, if you're using ensureBond(), the call should finish at line 399: https://github.com/NordicSemiconductor/Android-BLE-Library/blob/004e6645dfb391c253c13a8b75d38a86b0aeacc2/ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java#L399-L403

Could you post the logs, so that I can trace what's going on there?

philips77 commented 1 year ago

Ok, I did some digging. When you call ensureBond(), and the device is already bonded, Android will remove bonding and bond again: https://github.com/NordicSemiconductor/Android-BLE-Library/blob/004e6645dfb391c253c13a8b75d38a86b0aeacc2/ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java#L788-L803

When removing bond completes (which by the way will disconnect the device), this will be called: https://github.com/NordicSemiconductor/Android-BLE-Library/blob/004e6645dfb391c253c13a8b75d38a86b0aeacc2/ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java#L370-L375

and the CREATE_BOND request will be started.

Then, when bonded, you should get: https://github.com/NordicSemiconductor/Android-BLE-Library/blob/004e6645dfb391c253c13a8b75d38a86b0aeacc2/ble/src/main/java/no/nordicsemi/android/ble/BleManagerHandler.java#L399-L403 which should also call nextRequest(true) after the switch.

philips77 commented 1 year ago

Logs from log(...) method would be helpful.

philips77 commented 11 months ago

When testing on Pixel 5 with Android 14 the following scenario:

  1. Connect
  2. Read a characteristic which triggers bonding

The phone bonds successfully and I'm getting read result afterwards:

12:09:05.401 BlinkyManagerImpl        V  Reading characteristic 00001524-1212-efde-1523-785feabcd123
12:09:05.435 BlinkyManagerImpl        D  gatt.readCharacteristic(00001524-1212-efde-1523-785feabcd123)
12:09:05.436 BluetoothGatt            D  onConnectionUpdated() - Device=7F:C6:12:4E:9F:70 interval=36 latency=0 timeout=500 status=0
12:09:05.446 BlinkyManagerImpl        I  Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
12:09:07.758 BlinkyManagerImpl        D  [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PASSKEY_CONFIRMATION (2); key: 758840
12:09:07.768 BlinkyManagerImpl        D  [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
12:09:07.911 BluetoothGatt            D  onConnectionUpdated() - Device=7F:C6:12:4E:9F:70 interval=6 latency=0 timeout=500 status=0
12:09:07.913 BlinkyManagerImpl        I  Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
12:09:11.532 BlinkyManagerImpl        D  [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
12:09:11.539 BlinkyManagerImpl        I  Device bonded
12:09:11.544 BlinkyManagerImpl        I  Read Response received from 00001524-1212-efde-1523-785feabcd123, value: (0x) 01

What phone and Android version are you working with?

ElectronicSpaceCat commented 3 months ago

I've had issues similar to this with the following scenario:

What fixed it for me was changing the 2 instances of:

 if (request != null && request.type == Request.Type.CREATE_BOND) { 
    request.notifySuccess(device); 
    request = null; 
    break; 
 } 

to:

 if (request != null && (request.type == Request.Type.CREATE_BOND || request.type == Request.Type.ENSURE_BOND)) { 
    request.notifySuccess(device); 
    request = null; 
    break; 
 } 
philips77 commented 3 months ago

Could you prepare another PR with that change? I think it seems legit.