Skip to content

Commit

Permalink
Handle bluetooth adapter state changes (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
cedrickcooke authored Jul 8, 2021
1 parent 5d47d39 commit d9ff2ce
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
24 changes: 24 additions & 0 deletions core/src/androidMain/kotlin/BluetoothStateBroadcastReceiver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.juul.kable

import android.bluetooth.BluetoothAdapter
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter

private val bluetoothStateIntentFilter: IntentFilter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)

private inline fun bluetoothStateBroadcastReceiver(
crossinline action: (state: Int) -> Unit,
): BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
action.invoke(state)
}
}

internal inline fun registerBluetoothStateBroadcastReceiver(
context: Context = applicationContext,
crossinline action: (state: Int) -> Unit,
): BroadcastReceiver = bluetoothStateBroadcastReceiver(action)
.also { context.registerReceiver(it, bluetoothStateIntentFilter) }
19 changes: 15 additions & 4 deletions core/src/androidMain/kotlin/Peripheral.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.juul.kable

import android.bluetooth.BluetoothAdapter.STATE_OFF
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic.PROPERTY_INDICATE
Expand Down Expand Up @@ -113,8 +114,18 @@ public class AndroidPeripheral internal constructor(
private val onServicesDiscovered: ServicesDiscoveredAction,
) : Peripheral {

private val receiver = registerBluetoothStateBroadcastReceiver { state ->
if (state == STATE_OFF) {
closeConnection()
_state.value = State.Disconnected()
}
}

private val job = SupervisorJob(parentCoroutineContext[Job]).apply {
invokeOnCompletion { dispose() }
invokeOnCompletion {
applicationContext.unregisterReceiver(receiver)
closeConnection()
}
}
private val scope = CoroutineScope(parentCoroutineContext + job)

Expand Down Expand Up @@ -172,14 +183,14 @@ public class AndroidPeripheral internal constructor(
onServicesDiscovered(ServicesDiscoveredPeripheral(this@AndroidPeripheral))
observers.rewire()
} catch (t: Throwable) {
dispose()
closeConnection()
throw t
}

ready.value = true
}

private fun dispose() {
private fun closeConnection() {
_connection?.close()
_connection = null
}
Expand All @@ -196,7 +207,7 @@ public class AndroidPeripheral internal constructor(
suspendUntilDisconnected()
}
} finally {
dispose()
closeConnection()
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/jsMain/kotlin/Peripheral.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class JsPeripheral internal constructor(
) : Peripheral {

private val job = SupervisorJob(parentCoroutineContext.job).apply {
invokeOnCompletion { dispose() }
invokeOnCompletion { closeConnection() }
}

private val scope = CoroutineScope(parentCoroutineContext + job)
Expand Down Expand Up @@ -143,7 +143,7 @@ public class JsPeripheral internal constructor(
ready.value = true
}

private fun dispose() {
private fun closeConnection() {
observationListeners.clear()
disconnectGatt()
unregisterDisconnectedListener()
Expand Down

0 comments on commit d9ff2ce

Please sign in to comment.