Closed Rawa closed 6 years ago
Hello!
So I was hoping, that both approaches are working. They both should. If not, there's a bug. Do you have a small app that I could use for debugging? I would really like to test it. I can try with some samples from our SDK.
Any idea why the other requests below createBond() are ignored? Did you try to debug it?
Regarding error 8, it can be found here: https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/stack/include/gatt_api.h#36
Yes, I have an example. I need to clean it up a bit but I can provide it later today.
https://github.com/Rawa/Android-BLE-Library-32
Currently showcases the last bug, producing the "error 8", do produce the other on you can just add the bondRequest and the rest of the request will be dropped. You'll have to change the model and the BluetoothServices to match you device. I've tried slimming it down as much as possible while still making it usable. If you have any questions feel free to ask me.
Thanks! Do you have any HEX file that I could quickly drop on my nRF5x DK, or you are working on some special hardware? I can use any of the samples, or replicate it using 2 Android phones and nRF Connect, so no problem if that's not possible.
We using a nRF52832. However, I can not provide a HEX file since we are not the producer of the firmware and it is integrated into the hardware we are using.
Hi, so with the changes I made the createBond().enqueue()
in initialization should work now. Also, I wonder what happens when you will use the latter approach. It will now go into the if statement, as I added == 8 there, but will the bond be started? Will library repeat reading after bond is complete? Could you verify this?
Also, in the new version I removed dependency to nRF Logger. The log(...)
method will do nothing now, so you have to override it to get logs with lower then warning priority.
I can release the version beta6 (I think I should start moving to gamma now ;) ) tomorrow if it works for you.
Hi! I'll try this out tomorrow and i'll come back to you with an answer when I have access to all the equipment
Hi, did you have time to look into that?
Hello @philips77!
Sorry for late response. I've been very busy today so this got put off a bit. But yes, I can now confirm that createBond().enqueue() does work as intented! The second example do not work, (reading a bond characteristic straight away) does not work.
I also had some troubles running the project after importing it. Since I'm using the Jetifier and Androidx the annotations could not be loaded. Had to manually search and replace to get your code base to run. Working with the library do you know if there is a simpler way?
What phone and Android version were you testing on? I'm trying to get GATT INSUF AUTHORIZATION error.
Regarding annotations, jetifier should port android.support annotations to androidx. At least I thought so. I've also added (17096338124604c9ac1edb3cee57e2d9d34aa067) many more annotations, with range, type, etc.
I will release beta6 now and try porting nRF Blinky app to AndroidX to see how it works.
2.0-beta6 released.
@philips77 I no longer seem to be able to reproduce the error. However, the still same applies:
Galaxy S9:
override fun initialize() {
super.initialize()
readCharacteristic(modeCharacteristics).with(modeCallback).enqueue()
readCharacteristic(bondCharacteristics).with(bondDataCallback).enqueue()
setNotificationCallback(modeCharacteristics).with(modeCallback)
enableNotifications(modeCharacteristics).enqueue()
}
Nothing happens after readCharacteristics(bondCharacteristics)
without explicitly doing createBond().enqueue()
before reading from the bond characteristic. So basically connect never ends up finishing. It seems like it ends up blocking because it is unable to read from the bonded characteristic.
Same is issue reproducible on a Google Pixel XL. I have some other phones I can test on if needed as well (e.g Oneplus 6, and P20 Pro)
Further testing yields in the same result. E.g Try and connect to a device, then (after connected) read from a characteristic that requires bond. It will lock up all reads from that device and not create a bond or call the onBondingRequired callback.
I'm not sure what the desired behavior is, if reading a char that needs bond should create a bond or not. I'm just assuming it shouldn't lock up the queue without producing any error.
Android should initiate bonding automatically. The lib should proceed (repeat the last operation (on older Android versions) or wait until Android does it on its own (on newer)) after the bond is complete. I'll look into it. Perhaps there is something that should be done on the peripheral side? I'll test against another Android phone running nRF Connect and some of our samples from the SDK.
Hi @Rawa, First of all, nice piece of code this project of yours. We didn't start with Kotlin yet, and I have troubles with understanding, that good it is :) I already know Swift, but Kotlin, with those hundreds of extensions and inline functions, is the next level. I hope we can start the Kotlin adventure soon.
Secondly, I tried your app, as I said, with another Android phone running nRF Connect. Your app was running on Pixel 2 with Pie, while nRF Connect on Nexus 5X with Android 8.1. I set up 2 services, and added 3 characteristics, based on MyBleManager. The Pairing characteristic had Read encrypted permission (requires just works bonding). Your app connected, initiated bonding by reading this characteristic, paired (I had to click 2 times Pair on the target phone and once on master phone), read everything, reported Ready and read Pairing again. Here are logs:
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=8 mScannerId=0
D/DeviceFragment: Address: 43:86:C5:B2:94:F6
D/DeviceManager: BeforeConnect: false
V/BleLibrary: Connecting...
D/DeviceManager: onDeviceConnecting
D/BleLibrary: gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, LE 1M)
D/BluetoothGatt: connect() - device: 43:86:C5:B2:94:F6, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=75067124-38be-4a39-8e76-77e0af918e1f
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=9
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=9 device=43:86:C5:B2:94:F6
D/BleLibrary: [Callback] Connection state changed with status: 0 and new state: 2 (CONNECTED)
I/BleLibrary: Connected to 43:86:C5:B2:94:F6
D/DeviceManager: onDeviceConnected
D/BleLibrary: wait(300)
V/BleLibrary: Discovering services...
D/BleLibrary: gatt.discoverServices()
D/BluetoothGatt: discoverServices() - device: 43:86:C5:B2:94:F6
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=6 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D/BluetoothGatt: onSearchComplete() = Device=43:86:C5:B2:94:F6 Status=0
I/BleLibrary: Services discovered
V/BleLibrary: Primary service found
D/DeviceManager: onServicesDiscovered
// Reading Pairing initiated
V/BleLibrary: Reading characteristic 00001820-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.readCharacteristic(00001820-1212-efde-1223-785feabcd123)
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=36 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=6 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
// Device started to bond
D/BleLibrary: [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D/DeviceManager: onBondingRequired
D/BleLibrary: [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PASSKEY_CONFIRMATION (2)
// Automatically, when devices are bonded, the Android returns read value (even before state is BONDED)
I/BleLibrary: Read Response received from 00001820-1212-efde-1223-785feabcd123, value: (0x) 01
D/DeviceManager: onBondChanged
// The lib proceeds with next read (FunctionMode)
V/BleLibrary: Reading characteristic 00001554-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.readCharacteristic(00001554-1212-efde-1223-785feabcd123)
// Finally the broadcast comes, notifying that we are bonded
D/BleLibrary: [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
I/BleLibrary: Device bonded
D/DeviceManager: onBonded
// But the lib just continues to receive requested data
I/BleLibrary: Read Response received from 00001554-1212-efde-1223-785feabcd123, value: (0x) 06-00
D/DeviceManager: onFunctionModeChanged: Init()
D/BleLibrary: gatt.setCharacteristicNotification(00001554-1212-efde-1223-785feabcd123, true)
D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001554-1212-efde-1223-785feabcd123 enable: true
V/BleLibrary: Enabling notifications for 00001554-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
I/BleLibrary: Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
I/BleLibrary: Notifications enabled
D/BleLibrary: gatt.setCharacteristicNotification(00001591-1212-efde-1223-785feabcd123, true)
D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001591-1212-efde-1223-785feabcd123 enable: true
V/BleLibrary: Enabling notifications for 00001591-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=36 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
I/BleLibrary: Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
I/BleLibrary: Notifications enabled
// Device is ready
D/DeviceManager: onDeviceReady
D/DeviceManager: connect Success
// You read Pairing again in connect's done callback
V/BleLibrary: Reading characteristic 00001820-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.readCharacteristic(00001820-1212-efde-1223-785feabcd123)
I/BleLibrary: Read Response received from 00001820-1212-efde-1223-785feabcd123, value: (0x) 01
D/DeviceManager: onBondChanged
Does it work on an iPhone? Is your device returning the correct error when you try to read protected characteristic? Shouldn't it be INSUF AUTHENTICATION, not INSUF AUTHORIZATION? Are you able to sniff it, or get the HCI logs from the phone? Could you also try Proximity sample from our SDK, which is also using automatic just-works pairing when the app tries to write alert level.
Thank you, I quickly made that project together so it is not all clean but readable enough I hope. Working with Kotlin makes everything so much easier. I've been doing Kotlin for almost a year now (coming from a Java background) and I can tell you it has many benefits, and you should definitely consider switching to it.
I reproduced your test case, setting up a phone provding the services and indeed it does bond. I'm starting to believe this issue probably is caused by our device. I'm gonna close this issue for now until I can find something that points towards otherwise.
Thank you again for your great work with this library.
Great! We are then almost ready with releasing it as 2.0-final. I'm just busy fixing bugs in DFU, I didn't look there since long time... Thanks for the help with the library!
Hello again!
Thanks for you last fix, it solved my issue. :) I've ran into another strange case. Let's say you want to connect to a device and bond that device. What is the flow for this? I've tried several different ways but ran into different issues.
enqueue a bond in the initialization?
In the case above everything below createBond() will be ignored.
In this case I get:
It does not seem to match the BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION, see https://github.com/NordicSemiconductor/Android-BLE-Library/blob/master/ble/src/main/java/no/nordicsemi/android/ble/BleManager.java#L1316 However, it will log in the nRF Logger: Error (0x8): GATT INSUF AUTHORIZATION.
Or is the right way to go to create a bond after connect done callback and then do additional reading for characteristics that require bond?