Additional

Commercial

BleGattCoroutines

Make Gatt Great Again! This library allows easy and safer usage of BluetoothGatt in Android. It has also been tested successfully on Android Wear, with the sample included in this repository. It should work similarly on other Android variants such as Android Things.

It does so by taking advantage of the excellent coroutines feature in the Kotlin programming language that allows to write asynchronous code in a sequential/synchronous style, which means, without the callback hell, and without blocking any thread (which would waste memory and decrease performances).

This library makes it possible to have readable and debuggable code that interacts with Bluetooth Low Energy GATT (General Attribute), that is, the connection part of the Bluetooth Low Energy standard.

Why this library ?

As we needed to have an Android app interact with a Bluetooth Low Energy device, we found the Android BluetoothGatt API and a few RxJava libraries built on top of it. Unfortunately, none suited our needs:

The vanilla Android BluetoothGatt API is extremely hard to get right, because you have to provide a single instance of what we call a "God Callback", that is, an instance of a class with overridable methods that asynchronously receive the results off all operations of a given type (for example, the result of a characteristic you requested to read, or the result of whether a characteristic write went well or failed. You're on your own to make readable code with this, where unrelated characteristic reads, writes or other operation types are dispatched in the same callback method (like onCharacteristicRead(…)).

Experimental status

This library is based on the coroutines feature of Kotlin, as well as the kotlinx.coroutines library, which are both under the experimental status. Consequently, this library inherits this experimental status. Also, we are expecting to make a few API changes based on your feedback and real world usages to improve this library.

Since the API design it not final at the moment, we're very open to feedback while you're using this library.

Please, open an issue if something can be improved. If you just want to tell the author what you're doing with this library, feel free to reach out via Twitter DM, or public tweet.

Usage

As usual, scan BLE devices using BluetoothLeScanner to find you BluetoothDevice, or create an instance from the MAC address of your target device.

With this BluetoothDevice instance, you can create a GattConnection object, which will be key to perform Bluetooth GATT operations using coroutines.

On this GattConnection object, call connect() to initiate the connection. Immediately after It will suspend until the connection is established, then you use the connection:

The currently supported GATT operations on the GattConnection class are:

Services discovery, using discoverServices() which returns and cache the list of the services on the connected device.

Characteristic read, using readCharacteristic(…). Services discovery has to be completed before, as usual.

Characteristic write, using writeCharacteristic(…). Services discovery has to be completed before, as usual.

ReliableWrite, with reliableWrite { … }. Implemented, but could not be tested yet. Open an issue if your device supports it

Descriptor read, using readDescriptor(…). Services discovery has to be completed before, as usual.

Descriptor write, using writeDescriptor(…). Services discovery has to be completed before, as usual.

RSSI read, using readRemoteRssi(…).

NOTIFY characteristics with the notifyChannel. These haven't been tested yet. Feedback wanted.

The snippet below is the example you can find in the sample, powered by two extension methods for brevity (deviceFor(…) and useBasic { device, services -> … }). It also uses the GenericAccess object, which is the definition of the standard Bluetooth GATT "Generic access". It includes extension functions and properties for easy and readable usage. You can write a similar specification for any BLE device or BluetoothGattService you want.

When connected to my Google Beacon, the code above outputs the following in logcat:

I/MainViewModel$logNameAndAppearance: Connected!I/MainViewModel$logNameAndAppearance: Services discovered!D/MainViewModel$logNameAndAppearance: Service found with UUID: 00001800-0000-1000-8000-00805f9b34fbD/MainViewModel$logNameAndAppearance: Service found with UUID: 00001801-0000-1000-8000-00805f9b34fbD/MainViewModel$logNameAndAppearance: Service found with UUID: ee0c2080-8786-40ba-ab96-99b91ac981d8D/MainViewModel$logNameAndAppearance: Device appearance: 512D/MainViewModel$logNameAndAppearance: Device name: eddystone ConfigI/MainViewModel$logNameAndAppearance: Disconnected!I/MainViewModel$logNameAndAppearance: Closed!

This proves our library is working and that WE MADE GATT GREAT AGAIN!

Download

Gradle instructions

Make sure you have jcenter() in the repositories defined in your project's (root) build.gradle file (default for new Android Studio projects).

Add the version of the library to not repeat yourself if you use multiple artifacts, and make sure their versions are in sync by adding an ext property into your root project build.gradle file:

allProjects {
ext {
blegattcoroutines_version ='0.1.0'
}
}

Here are all the artifacts of this library. Just use the ones you need: