[labs.beatcraft.com]]
Android
BLE is the abbreviation of Bluetooth Low Energy and a part of Bluetooth 4.0 standard.
Technical Overview:
- Ultra-low power consumption (being capable of operating more than a year in a button battery.)
- No compatibility with the previous version of Bluetooth (Classic Bluetooth)
- Communication distance is 2.5m to 10m.
- A single BLE unit does not have restrictions on the number of concurrent connections. (Classic Bluetooth allows a single unit to connect with 7 units at most.)
In the communication of BLE, GATT (Generic Attribute Profile), a client-server model, is employed.
A device (server) consists of Profile (GATT), Service, Characteristic, and Descriptor. The diagram below describes the design of model.
GATT (Generic Attribute Profile) is a theoretical design for data communication between BLE devices.~ This handles to read the data structure, to write data, and to notify the change in data.
GATT consists of three elements, such as Service, Characteristic, and Descriptor.
Profile does have more than one Service.
Service shows the functions of Profile.
Service consists of several nesting Services and several Characteristics.
Characteristic does have a single value, which indicate its attribute.
It consists of own value, property, which defines how to access the value, and several Descriptors.
Descriptor shows the attribute value, which is used when a characteristic needs the additional information.
Some Characteristics do NOT contain any Descriptors.
Android 4.3 or above (API Level 18 or greater) supports BLE.
android.bluetooth.*
It manages the functions of Bluetooth.
It acquires BluetoothAdapter from BluetoothAdapter.
It controls Bluetooth set at a mobile device.
It scans Bluetooth devices.
It operates GATT profile.
It manages the search for Services, and the configuration of Descriptor.
It receives the scanning results of BluetoothAdapter.
It is the information of Bluet device.
It is the information of (GATT) Services. It holds Characteristic (BluetoothGattCharacteristic).
It is the information of Characteristic.
It holds Descriptor (BluetoothGattDescriptor). Some Characteristics do NOT have Descriptors.
The information of Descriptor.
Please add these tags listed below to Manifest (AndroidManifest.xml) for making BLE effective.
Configuration for Permission<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Please add the tag to Manifest for making sure that the API only work with Android devices, which support BLE.<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter();
As the app is executed, this checks whether Bluetooth function is available or not, If BLE is not effective, a dialog appears for confirmation to make BLE effective.
BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { return false; } // Checking Bluetooth function effective or not. If it is not effective, a dialog appears for confirmation to enable BLE if (mBluetoothAdapter.isEnabled()) { // Bluetooth is effective } else { // Bluetooth is NOT enabled, and the confirmation dialog appears. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(enableBtIntent, 1); }
// Stop scanning 10 seconds later. private static final long SCAN_PERIOD = 10000; ... private void scanLeDevice(final boolean enable) { if (enable) { // Stops scanning after a pre-defined scan period. mHandler.postDelayed(new Runnable() { @Override public void run() { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }, SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } ... } private LeDeviceListAdapter mLeDeviceListAdapter; ... // The callback function after device scanning is completed 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() { String msg = "name =" + device.getName() + ", bondstate = " + device.getBondState() + ", address = " + device.getAddress() + ", type" + device.getType() + ", uuid = " + device.getUuid().toString(); Log.d("Scan", msg);} }); } };
Call BluetoothDevice$connectGatt(), which is returned form onLeScan(), and connect with a device.
BluetoothDevice: BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)
private final BluetoothGattCallback callback = new BluetoothGattCallback() { // This is executed when the status of connection is changed. @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // It is connected if (newState == BluetoothProfile.STATE_CONNECTED) { Log.i(TAG, "Connected to GATT server."); // Searching for Services Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); // It is disconnected. } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i(TAG, "Disconnected from GATT server."); } } @Override // Return the search results of Services public void onServicesDiscovered(BluetoothGatt gatt, int status) { // Success if (status == BluetoothGatt.GATT_SUCCESS) { // Acquire the list of Services. List<BluetoothGattService> gattService = getSupportedGattServices(address); for(BluetoothGattService service : gattService) { UUID uuid = service.getUuid(); // Acquire the list of Characteristics from Services. List<BluetoothGattCharacteristic> charastics = service.getCharacteristics(); // Set up Characteristic for a reception request of Notification for(BluetoothGattCharacteristic charastic : charastics) { // gatt.setCharacteristicNotification(charastic, true); } } } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } // Notification for reading @Override public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully read. } } // Notification for writing @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully written. } ... };
Since reading is asynchronous, the reading process requires reading request and reading notification.
Execute BluetoothGatt#readCharacteristic().
The results are returned to BluetoothGattCallBack#onCharacteristicRead().
mBluetoothGatt.readCharacteristic(characteristic);
public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully read. } }
Since writing is asynchronous, the writing process requires writing request and writing notification.
Execute BluetoothGatt#writeCharacteristic()
The results are returned to BluetoothGattCallBack#onCharacteristicWrite().
mBluetoothGatt.writeCharacteristic(characteristic);
public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully written. } }
Execute BluetoothGatt#close().
To connect multiple devices, do not connect them simultaneously but connect them one by one.
If the new connection attempt is started before the current connection attempt has been completed, the operation of device becomes unstable.
If the new connection attempt is started before the scanning process is ended, the operation of device also becomes unstable.
Connect with Device A, B, and C.
1. Connect to Device A BluetoothDevice#connectGatt() 2. Wait for the results of connection to Device A BluetoothGattCallback#onConnectionStateChange() 3. Connect to Device B BluetoothDevice#connectGatt() 4. Wait for the results of connection to Device B BluetoothGattCallback#onConnectionStateChange() 5. Connect to Device C BluetoothDevice#connectGatt() 6. Wait for the results of connection to Device C BluetoothGattCallback#onConnectionStateChange()
Exhibiting a single Android device is connected to 6 BLE devices, demonstrate how to handle these 6 devices with BLE connection.
Multiple BLE devices are connected.
6 devices are connected one by one.
There are three LED lights, and each light is capable of shifting six different brightness. The brightness of LED lights is changed individually or collectively.
Employing three relays, turn on/off LED lights. It manages LEDs individually or collectively.
It controls the color (RGB) of LED color light valve.
- 2016-02-19 This article is initially released.