Search code examples
androidbluetooth-lowenergyrx-androidrxandroidble

RxAndroidBle: JustWorks bonding and operation timeout issue


I am dealing with characteristics that need encryption, so Android will automatically create a bond to perform the write/read operations.

There is a possibility that a bond will be automatically created by the OS. This usually happens when a read/write request is sent to a characteristic that needs encryption. (reference here)

However, the first read/write operation will fail with a timeout (the default in the library is 30 seconds), but if I retry the operation immediately after it works because the bond was created.

I know that the first read/write operation will always fail because of the bonding thing, so I want to perform it as quickly as possible, and not wait for 30 seconds to fail. In order to do that, what I did was to establish a 10 seconds timeout for the whole connection like this:

scaleDevice.establishConnection(false, new Timeout(10, TimeUnit.SECONDS))

However, I would like to be able to change the operation timeout after establishing the connection, so I can do the following:

  1. Establish the connection with the default 30 seconds operation timeout.
  2. Before I need to read/write for the first time to an encrypted characteristic, I want to set the timeout to a small value (maybe 5 seconds).
  3. The first read/write operation to the encrypted characteristic will fail after 5 seconds.
  4. I will retry the operation and now it will succeed.
  5. I want to set the operation timeout back to 30s.

Is that possible in the current version of the RxAndroidBle library?


Solution

  • I checked the source code of the library and I realized that changing the Timeout after establishing the connection is not possible in the current version of the library.

    I opened an issue suggesting to add this functionality in the future.

    Regarding the bonding and encrypted characteristics problems, I came up with a better workaround. Instead of waiting for an automatic bonding after the first failed operation, I make sure to be bonded before establishing the connection. I achieved that by calling the bondWithDevice method available in this helper class like this:

    BondingHelper.bondWithDevice(this, scaleDevice, 30, TimeUnit.SECONDS)
                        .andThen(scaleDevice.establishConnection(false))
                        .observeOn(AndroidSchedulers.mainThread())
                        .doFinally(this::disposeConnection)
                        .subscribe(this::connectionEstablished, this::throwException);