I am trying to create an application that connects and receives notifications from multiple bluetooth low energy devices. I am wondering how this can be achieved. Do I need a separate thread for each connection? How can I make sure the services get discovered and notifications get set in an order that works given the asynchronous nature of the API. I am currently using the same structure provided here: https://developer.android.com/guide/topics/connectivity/bluetooth-le.html. This is setup for a single connection only. Would I be able to keep this structure i.e. extending the Service class in the BluetoothLeService class and binding to the service. I have recently discovered that The Service class is a singleton so how would I go about creating different instances of my BluetootLeService class and receiving broadcast and registering the Broadcast Receiver/Receivers to handle changes from the appropriate devices.
Have a look at this question regarding multiple BLE connections on Android. YES, it is possible to connect from one application to multiple BLE devices
If Bluetooth is available, the device will scan for nearby BLE devices. Once a device is found, the capabilities of the BLE device are discovered by connecting to the GATT server on the BLE device. Once a connection is made, data can be transferred with the connected device based on the available services and characteristics.
As what I learnt from BLE4.x protocol SPEC, when the iPhone/Android phone play as role of BLE central mode, the limitation to have active connection at the same time is up to 8 devices. But from what we observed, iPhone 8 can connect and collect data from our module up to 10 units at the same time!
Most Android devices can connect to two or five Bluetooth devices simultaneously, while others support up to seven devices. The number of supported connections depends on the Bluetooth module your device is equipped with. Obviously, the newer the hardware, the more Bluetooth devices you can connect to.
I am wondering how this can be achieved
To achieve multiple BLE connection you have to store multiple BluetoothGatt
object and use those object for different device. To store multiple connection object of BluetoothGatt
you can use Map<>
private Map<String, BluetoothGatt> connectedDeviceMap;
On Service onCreate
initialize the Map
connectedDeviceMap = new HashMap<String, BluetoothGatt>();
Then before calling device.connectGatt(this, false, mGattCallbacks);
to connect to GATT Server check that device is already connected.
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);
int connectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if(connectionState == BluetoothProfile.STATE_DISCONNECTED ){
// connect your device
device.connectGatt(this, false, mGattCallbacks);
}else if( connectionState == BluetoothProfile.STATE_CONNECTED ){
// already connected . send Broadcast if needed
}
On BluetoothGattCallback
if connection state is CONNECTED then store BluetoothGatt
object on Map
and if connection state is DISCONNECTED then remove it form Map
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
BluetoothDevice device = gatt.getDevice();
String address = device.getAddress();
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
if (!connectedDeviceMap.containsKey(address)) {
connectedDeviceMap.put(address, gatt);
}
// Broadcast if needed
Log.i(TAG, "Attempting to start service discovery:" +
gatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
if (connectedDeviceMap.containsKey(address)){
BluetoothGatt bluetoothGatt = connectedDeviceMap.get(address);
if( bluetoothGatt != null ){
bluetoothGatt.close();
bluetoothGatt = null;
}
connectedDeviceMap.remove(address);
}
// Broadcast if needed
}
}
Similarly onServicesDiscovered(BluetoothGatt gatt, int status)
method you have BluetoothGatt
connection object on parameter and you can get device from that BluetoothGatt
. And other callback method like public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
you will get the device form gatt
.
When you need to writeCharacteristic or writeDescriptor, get BluetoothGatt
object from Map
and use that BluetoothGatt
object to call gatt.writeCharacteristic(characteristic)
gatt.writeDescriptor(descriptor)
for different connection.
Do I need a separate thread for each connection?
I think you don't need to use separate Thread for each connection. Just run the Service
on a Background Thread.
Hope this help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With