RxAndroidBle icon indicating copy to clipboard operation
RxAndroidBle copied to clipboard

Bonding best practices

Open skykelsey opened this issue 6 years ago • 11 comments

I needed to initiate a bond with a peripheral using "Just Works" bonding. This means no exchange of a PIN. I got it to work by simply grabbing the underlying BluetoothDevice and calling createBond(), but I wanted to check to see if this is somehow wrong, and I should be doing something else, or in a more idiomatic way.

val device: RxBleDevice = bluetoothService.getBleDevice(selectedDevice.macAddress)

Observable.fromCallable<RxBleDevice> {
	device.bluetoothDevice.createBond()
	device
}
.flatMap {
	it.establishConnection(false)
}
.doOnNext {
	Timber.e("Connection established.")
}
...

skykelsey avatar Apr 26 '18 00:04 skykelsey

There are currently no guidelines nor even too much tests with this library using bonding. It the terms of code expressiveness you approach is ok. You could also write it like this:

val device: RxBleDevice = bluetoothService.getBleDevice(selectedDevice.macAddress)

Observable.defer<RxBleConnection> {
	device.bluetoothDevice.createBond() // it is a blocking function
	device.establishConnection(false) // return Observable<RxBleConnection>
}
.doOnNext {
	Timber.e("Connection established.")
}

dariuszseweryn avatar Apr 26 '18 14:04 dariuszseweryn

I took a stab at making a Java version. Please comment (in particular, is there a better exception type to use?):

    public static Observable getBondedConnectionObservable( RxBleDevice device ) {
        return Observable.defer( () -> {
            if( device.getBluetoothDevice().createBond() ) {  // bonding will begin
                return device.establishConnection( false );
            } else {  // immediate error
                return Observable.error( new IOException( "Error initiating bonding of device " + device.getName() ) );
            }
        });
    }

RobLewis avatar Apr 26 '18 16:04 RobLewis

Actually createBond returns immediately, and you need to create a broadcast receiver to listen for the updated bond states. https://developer.android.com/reference/android/bluetooth/BluetoothDevice#createbond

Here's an example: https://stackoverflow.com/questions/18197444/android-bluetooth-low-energy-pairing?rq=1 The receiver operates the same whether you initiate the bond request yourself or the system does in response to a GATT_INSUFFICIENT_AUTHENTICATION error.

nateridderman avatar Apr 27 '18 18:04 nateridderman

@nateridderman Once again the "pairing" vs. "bonding" semantics confuse things. From everything I can determine, they are not the same thing, even though many people—including Google in their official Android docs—use the terms interchangeably. As explained fairly well here, pairing refers to a client-initiated exchange of security features, based on a temporary encryption key. Bonding means that these encryption keys are then remembered by the devices, so the next time they connect they can use those keys without exchanging any unsecured information.

RobLewis avatar Apr 27 '18 19:04 RobLewis

Right, they are related but slightly different concepts. This site has a good explanation - https://eewiki.net/display/Wireless/A+Basic+Introduction+to+BLE+Security#ABasicIntroductiontoBLESecurity-PairingOverview:

nateridderman avatar Apr 27 '18 20:04 nateridderman

I'm not sure but when I was try using createBond it not work well. @skykelsey Can you describe your case of bonding ? It is very interesting for me :)

ardmn avatar May 03 '18 08:05 ardmn

Hello,

Here is a way to implement pairing/bonding with RxAndroidBle. It might be useful for people having to deal with that process.

https://gist.github.com/craigzour/edf7f3bd8bef4b162887b4244e27dc1f

craigzour avatar May 10 '18 13:05 craigzour

@craigzour Were you actually able to get the BOND_BONDED Intent? I'm not seeing that. Seems like it's not always emitted.

skykelsey avatar Aug 27 '18 22:08 skykelsey

@skykelsey Well at least with all the devices I have tested my code on it worked pretty well. The only thing that is kind of random and depends on devices is the way Android prompts the Pairing alert. Sometimes it goes silently in the notification center and thus you can miss it.

craigzour avatar Aug 28 '18 12:08 craigzour

I came up with a slightly different helper class based on @craigzour solution. The main difference is that in Craig's solution, the completable completed successfully if the device was already bonded. In my case, that wasn't useful, because when I try to read or write the first characteristic to be encrypted, the operation failed anyway. To avoid that, I always unbond and bond again before establishing the connection, so I added an unbonding operation before.

https://gist.github.com/dglozano/9b0ce38a558eeca16137909bd368698c

dglozano avatar Nov 22 '18 06:11 dglozano

@dglozano Would unbonding/bonding each time not be the same as not bonding at all? So far I understand, the point of bonding is to persist the encryption keys, so you would be regenerating the keys each time, which is what you do when there's no bonding.

ivnsch avatar May 02 '19 21:05 ivnsch