question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

BluetoothPerihheral - cancellation forcing the peripheral get disconnected after bonding failure and bonding lost.

See original GitHub issue

I am facing a strange issue.

Normally, I create a bond after the peripheral is connected.

if (bluetoothPeripheral.bondState == BondState.NONE) {
    bluetoothPeripheral.createBond()
}

It works fine. It appears an android request dialog to get user confirmation. If the user decline to get bonded, or wait for a time, I mean after bonding failed, the peripheral is starting to disconnect. I receive the disconnected callback, it is fine but the strange thing starts.

override fun onDisconnectedPeripheral(peripheral: BluetoothPeripheral, status: HciStatus) {
    val intent = Intent(ACTION_GATT_DISCONNECTED)
    mainHandler.post { context.sendBroadcast(intent) }
}

Normally, on each disconnected callback received, context.sendBroadcast(intent) works fine, but the callback after receive bonding failure does not send broadcast, I mean context.sendBroadcast(intent) does not work. In order to investigate the issue I put some different delays to try it.

override fun onDisconnectedPeripheral(peripheral: BluetoothPeripheral, status: HciStatus) {
    val intent = Intent(ACTION_GATT_DISCONNECTED)
    mainHandler.post { context.sendBroadcast(intent) } // did not work, I mentioned above
    mainHandler.postDelayed({ context.sendBroadcast(intent) }, 100) // did not work
    mainHandler.postDelayed({ context.sendBroadcast(intent) }, 150) // worked
    mainHandler.postDelayed({ context.sendBroadcast(intent) }, 200) // worked
    mainHandler.postDelayed({ context.sendBroadcast(intent) }, 300) // worked, and so on...
}

In order to send a broadcast via context.sendBroadcast(intent) I needed to delay it around 150ms for above issue. I can keep it as delayed 150ms, but it effects my all broadcasting system for other situations. (I suspect that the issue is happening because of android request dialog for user confirmation, some how.)

I investigate the package code in GitHub, I saw that after getting state of BOND_NONE, you are getting the peripheral disconnected in BluetoothPerihheral.java in the function private void handleBondStateChange(final int bondState, final int previousBondState).

Can you put some delay for this disconnection around 200ms in the function ?

case BOND_NONE:
    ...
    final Runnable disconnectRunnable = new Runnable() {
            @Override
            public void run() {
               disconnect()
            }
        };
    mainHandler.postDelayed(disconnectRunnable, 200);
    break;

Actually, bonding is an optional thing. You can extract disconnect() off for the case BOND_NONE. You don’t need to force the peripheral get disconnected. You can give us flexibility for choosing disconnect or not via bonding callbacks. For example I can keep the peripheral be connected if the user does not accept the android request for bonding, or I can get the peripheral disconnected via below callbacks.

override fun onBondLost(peripheral: BluetoothPeripheral) {
    peripheral.cancelConnection()
}

override fun onBondingFailed(peripheral: BluetoothPeripheral) {
    peripheral.cancelConnection()
}

If you do that, for the above issue (context.sendBroadcast(intent)) that I am facing currently, I can deal with myself either put delay or not.

If you ask my preference, I prefer you give us flexibility and don’t force the peripheral get disconnected if the case BOND_NONE.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
weliemcommented, Jul 7, 2021

Bonding itself is indeed optional in theory. However, in practice all devices I have worked with either demand it or not. So if a device demands a bond, then disconnecting when a bond is lost is the only sensible action to take. Otherwise nothing would work anymore.

Can you explain why in your situation it would be reasonable to make bonding optional?

Nonetheless, I don’t really understand why your context.sendBroadcast(intent) would fail. Seems totally unrelated. Also don’t understand why it would work with a delay…

Can you try to do the sendBroadcast directly, without posting it to a handler? Sendbroadcast is asynchronous anyway so there is no need to do it on a Handler. And worse even, the Handler is running on the main thread so that would interfere with any UI stuff that you say you are doing.

0reactions
talatkuyukcommented, Jul 9, 2021

I don’t want to customize this package for my usage. I am not expertise about ** android ble**, but I would like to contribute it. I think you would give developers flexibility and choose what they want to do. The package can be more responsive to the needs.

people will not know about and hence they won’t do it. You can easily write down in the documentation (we are reading the documentation), if bonding request is not successful you have to deal with the cancellation connection via callbacks.

I don’t know what the other developers who use this package think about this issue?

Read more comments on GitHub >

github_iconTop Results From Across the Web

CC2642R: Unable to scan and find again a peripheral after its ...
The problem in this case is that after the bonding process, If I disconnect the Launchpad and start again to scan for my...
Read more >
Bluetooth: Peripheral: Bond issue when using secure ... - GitHub
Disconnect ; Reconnect to the device; Try to retrieve all characteristics again; See error ... Re connection should work and allow to retrieve...
Read more >
BLE Peripheral disconnects every 3… - Apple Developer
The issue I am facing is that the peripheral is automatically disconnected exactly every 30 seconds, even while my notify value is set...
Read more >
Android 13: Unable to reconnect reliably to bonded peripheral
Have the app attempt to reconnect to this bonded peripheral without performing a BLE scan by using BluetoothAdapter.bondedDevices and filtering for the MAC ......
Read more >
How to Programmatically Handle BLE Peripheral Removing ...
event sm_bonding_fail(handle, result) # If bonding fails, handle it ... iOS cannot # Instead of disconnecting, just force a re-encryption.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found