Android BLE Overview

Niveditha Kabbur
Aug 23, 2017 · 4 min read

Bluetooth LE provides data transfers with low power consumption, making it possible to equip all types of sports and fitness equipment with wireless connectivity. Today, Bluetooth solutions span from basic fitness tracking to sophisticated devices that help fine tune the performance of professional athletes.

BLE is used in Bluetooth Mesh Networking, one of the technologies to implement Internet of Things (IoT).

Bluetooth Low Energy in Android: Android 4.3 introduces built-in platform support for Bluetooth Low Energy (BLE) in the central role and provides APIs that apps can use to discover devices, query for services, and transmit information.

BLE Central Role: The device in the central role scans, looking for advertisement.

BLE Peripheral Role: The device in the peripheral role makes the advertisement.

The android BLE permissions:

In order to use Bluetooth features in the application, the Bluetooth permission BLUETOOTH is required. It is needed to perform any Bluetooth communication, such as requesting a connection, accepting a connection, and transferring data.

The permissions has to be declared in the Android Manifest file.

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

Before starting the application, it is required to check if the device supports BLE, based on which the BLE related features can be disabled or enabled.

// Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}

Requesting Location Permissions for API 23+

The BLE requires the android location permissions because LE Beacons are often associated with location and without these permissions, scans won’t return any results.

Add the below code in the AndroidManifest.xml file.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Request permission to access the location.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}

Setting up the BLE of the android Device:

1) Get the Bluetooth Adapter:

The BluetoothAdapter is required for any and all Bluetooth activity. The BluetoothAdapter represents the device’s own Bluetooth adapter (the Bluetooth radio). There’s one Bluetooth adapter for the entire system, and the android application can interact with it using this object. The snippet below shows how to get the adapter.

private BluetoothAdapter mBluetoothAdapter;
...
// Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

2) Enable Bluetooth:

The following snippet checks whether Bluetooth is enabled. If it isn’t, the snippet displays an error prompting the user to go to Settings to enable Bluetooth.

// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

Scanning for BLE devices:

To start the scanning for BLE devices, the startLeScan() method is used. And to stop the scanning, the stopLeScan() method is used.

mBluetoothAdapter.startLeScan(mLeScanCallback); // To start the LE scan.mBluetoothAdapter.stopLeScan(mLeScanCallback); // To stop the LE scan.

Both the methods take BluetoothAdapter.LeScanCallback as the parameter. This callback must be implemented, because that is how scan results are returned.

The implementation of the BluetoothAdapter.LeScanCallback, which is the interface used to deliver BLE scan results is as below:

// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Add your code here
}
});
}
};

Connecting to a GATT server:

The first step in interacting with a BLE device is connecting to it — more specifically, connecting to the GATT server on the device. To connect to a GATT server on a BLE device, the connectGatt() method is used. This method takes three parameters: a Context object, autoConnect (boolean indicating whether to automatically connect to the BLE device as soon as it becomes available), and a reference to a BluetoothGattCallback.

mBluetoothGatt = device.connectGatt(this, false, mGattCallback);

The BluetoothGattCallback, provides various methods to get that information about the BLE devices.

// Various callback methods defined by the BLE API.
private final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {

...
}
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
...
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
...
}
}
...
};

Reading BLE Attributes:

Key BLE terms and concepts:

1) Generic Attribute Profile (GATT) — The GATT profile is a general specification for sending and receiving short pieces of data known as “attributes” over a BLE link. All current Low Energy application profiles are based on GATT.

2) Attribute Protocol (ATT) — GATT is built on top of the Attribute Protocol (ATT). ATT is optimized to run on BLE devices. Each attribute is uniquely identified by a Universally Unique Identifier (UUID), which is a standardized 128-bit format for a string ID used to uniquely identify information. The attributes transported by ATT are formatted as characteristics and services.

3) Service — A service is a collection of characteristics. For example, you could have a service called “Heart Rate Monitor” that includes characteristics such as “heart rate measurement.” A list of existing GATT-based profiles and services can be found on bluetooth.org.

4) Characteristic — A characteristic contains a single value and 0-n descriptors that describe the characteristic’s value. A characteristic can be thought of as a type, analogous to a class.

5) Descriptor — Descriptors are defined attributes that describe a characteristic value.

Once the Android app has connected to a GATT server and discovered services, it can read and write attributes, where supported.

There are different methods to obtain the services and the characteristics.

The gatt.discoverServices() is used to find all the services provided. It can be obtained in the onServicesDiscovered() method of the BluetoothGattCallback.

The getServices() method is used to to obtain the services and the getCharacteristics() method is used to get the characteristics.

The mBluetoothGatt.readCharacteristic() method is used to read the Characteristics.

The various methods provided by the BluetoothGattService can be found at https://developer.android.com/reference/android/bluetooth/BluetoothGattService.html

The various methods provided by the BluetoothGattCharacteristic can be found at https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html

More information on Gatt can be found at https://www.bluetooth.com/specifications/gatt

Sample code can be found at https://github.com/googlesamples/android-BluetoothLeGatt

Hope this is helpful.

)