# Recipes ## Basic Usage Example The following code snippet makes a connection to a [`BluetoothDevice`], reads a characteristic, then disconnects: ```kotlin val serviceUuid = "F000AA80-0451-4000-B000-000000000000".toUuid() val characteristicUuid = "F000AA83-0451-4000-B000-000000000000".toUuid() fun connect(context: Context, device: BluetoothDevice) = launch { val gatt = when (val result = device.connectGatt(context)) { is Success -> result.gatt is Failure -> throw result.cause } try { val characteristic = gatt.getService(serviceUuid).getCharacteristic(characteristicUuid) val result = gatt.readCharacteristic(characteristic) if (result.status == BluetoothGatt.GATT_SUCCESS) { println("result.value = ${result.value}") } else { // read characteristic failed } } finally { gatt.disconnect(timeout = 30_000L) } } private suspend fun Gatt.disconnect(timeout: Long) { withContext(NonCancellable) { withTimeoutOrNull(timeout) { disconnect() } } } ``` ## Coroutine Scopes ### Android `Activity` In the following example, the connection process is tied to the `Activity` lifecycle. If the `Activity` is destroyed (e.g. due to device rotation or navigating away from the `Activity`) then the connection attempt will be canceled. If it is desirable that a connection attempt proceed beyond the `Activity` lifecycle, then the [`launch`] can be executed using [`GlobalScope`], in which case the [`Job`] that [`launch`] returns can be used to manually cancel the connection process (when desired). ```kotlin class ExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val bluetoothDevice: BluetoothDevice = TODO("Retrieve a `BluetoothDevice` from a scan.") findViewById