Project has been deprecated, and superseded by Kable. If any needed features are available in Able but absent from Kable, please create an issue requesting the desired feature. Thank you.
The migration guide may be helpful for those transitioning from Able to Kable.
Provides a Kotlin Coroutines powered interaction with Android's Bluetooth Low Energy (BLE) framework.
See Recipes page for usage examples.
When feasible, the API closely matches the Android Bluetooth Low Energy API, replacing methods that
traditionally rely on BluetoothGattCallback
calls with suspension functions.
Android BluetoothDevice |
Able Device |
|
|
1 Suspends until STATE_CONNECTED
or non-GATT_SUCCESS
is received, or connectGatt
returns null
, then returns ConnectGattResult
:
sealed class ConnectGattResult {
data class Success(val gatt: Gatt) : ConnectGattResult()
sealed class Failure : ConnectGattResult() {
/** Connection could not be established (e.g. device is out of range). */
data class Connection(val cause: Exception) : Failure()
/** Android's `BluetoothDevice.connectGatt` returned `null` (e.g. BLE off or unsupported). */
data class Rejected(val cause: Exception) : Failure()
}
}
Android BluetoothGatt |
Able Gatt |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 Suspends until STATE_DISCONNECTED
or non-GATT_SUCCESS
is received, then calls close()
on underlying BluetoothGatt
.
3 Throws RemoteException
if underlying BluetoothGatt
call returns false
.
3 Throws GattResponseFailure
if an error occurs while waiting for response (e.g. connection is lost).
The primary entry point is the
BluetoothDevice.connectGatt(context: Context): ConnectGattResult
extension function. This
extension function acts as a replacement for Android's
BluetoothDevice.connectGatt(context: Context, autoConnect: Boolean, callback: BluetoothCallback): BluetoothGatt?
method (which relies on a BluetoothGattCallback
). The autoConnect
parameter is not
configurable (and is always false
).
Able expects that Android Bluetooth Low Energy is supported
(BluetoothAdapter.getDefaultAdapter()
returns non-null
) and usage prerequisites
(e.g. bluetooth permissions) are satisfied prior to use; failing to do so will result in
RemoteException
for most Able methods.
During the connectGatt
and disconnect
process, Able will ensure that connections are cleaned
up (i.e. close
will always be called on the underlying BluetoothGatt
) in the event of failure
or Coroutine cancellation:
fun connect(context: Context, device: BluetoothDevice) {
val job = launch {
device.connectGatt(context)
}
launch {
delay(1_000L) // Assume, for this example, that BLE connection takes more than 1 second.
// Cancels the `launch` Coroutine and automatically closes the underlying `BluetoothGatt`.
job.cancel()
}
}
Note that in the above example, if the BLE connection takes less than 1 second, then the
established connection will not be cancelled and result
will be
ConnectGattResult.Success
.
Once a connection is established (connectGatt
returns ConnectGattResult.Success
) then it will
remain connected until disconnect()
is called. It is the responsibility of the caller to clean up
the connection when no longer needed (via disconnect
).
To use Able in your Android project, setup your build.gradle
as follows:
repositories {
jcenter() // or mavenCentral()
}
dependencies {
implementation "com.juul.able:core:$version"
}
Able provides a number of packages to help extend it's functionality:
Package | Functionality |
---|---|
keep-alive |
Provides a keep-alive GATT (which automatically reconnects when connection is lost). |
processor |
A Processor adds the ability to process (and optionally modify) GATT datapre-write or post-read. |
throw |
Adds extension functions that throw exceptions on failures for various BLEoperations. |
timber-logger |
Routes Able logging through Timber. |
Copyright 2020 JUUL Labs, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.