Skip to content

Occasionally, turning BT off causes unrecoverable crash on Android #1200

Description

@bvitaliyg

Hey, and thank you for the library.

I found out that the code may thrown unrecoverable on Android.

First, BasePeripheral creates unscoped CoroutineScope:

    override val scope = CoroutineScope(
        SilentSupervisor() + CoroutineName("Kable/Peripheral/$identifier"),
    )

Then, BluetoothDeviceAndroidPeripheral creates repeatable action:

private val connectAction = scope.sharedRepeatableAction(::establishConnection)

The action calls checkBluetoothIsOn(), which throws when BT is off.

I have an IntentFilter-based Flow on whether BT is enabled.

When connect()/writeCharacteristic() methods call in a loop, sometimes it doesn't catch up with IntentFilter – and the exception is thrown. While this is userful for identifying the problems earlier, there's no way to recover from this exception.

Steps to reproduce:

btEnabledFlow.collect {
    val advertisement = advertisementsFlow.first() // that matches filters
    val peripheral = Peripheral(advertisement)
    peripheral.connect()
}

Then, rapidly switch BT on and off to increase chances of getting this error.

Potential solution: combine the scope with the coroutine scope that calls connect(), so that BT checkBluetoothIsOn() propagates to the parent scope (potentially cancelling it). Alternatively, throw from writeCharacteristic(), etc instead. Parent scope could also be be made required for creating Peripheral().

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions