Java – Android BLE multi-connection

Android BLE multi-connection… here is a solution to the problem.

Android BLE multi-connection

I’m trying to create an app that connects multiple Bluetooth low energy devices and receives notifications from them. I would like to know how to achieve this. Does each connection need a separate thread? Given the asynchronous nature of the API, how can I ensure that the order in which the discovery service and set up notifications is valid. I’m currently using the same structure provided here:
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html This is only set for a single connection. Can I keep this struct by extending the service class in the BluetoothLeService class and binding (bind) to the service. I recently discovered that the Service class is a singleton, so how would I create different instances of my BluetootLeService class and receive broadcasts and register broadcast receivers/receivers to handle changes from the appropriate devices.

Solution

I am wondering how this can be achieved

To implement multiple BLE connections, you must store multiple BluetoothGatt objects and use them for different devices. You can use Map<> to store multiple connection objects for BluetoothGatt

private Map<String, BluetoothGatt> connectedDeviceMap; 

The onCreate service initializes the Map

connectedDeviceMap = new HashMap<String, BluetoothGatt>();

Then call device.connectGatt(this, false, mGattCallbacks); Before connecting to the GATT server Check that the 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
  }

About BluetoothGattCallback, if the connection state is CONNECTED, then store objects on the BluetoothGatt Map and remove them if the connection state is DISCONNECTED Map delete

        @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) you have methods on the BluetoothGutt parameter on the connection object, from which you can get the device BluetoothGatt and other callback methods such as public void onCharacteristicChanged (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) You will get the device form gatt .

When writeCharacteristic or writeDescriptor is required, get the BluetoothGutt object from the Map and call it using the BluetoothGatt object gatt.writeCharacteristic(characteristic) gatt.writeDescriptor(descriptor) is used for different connections.

Do I need a separate thread for each connection?

I don’t think you need to use a separate Thread for each connection. Just run the Service on a background thread.

Hope this helps.

Related Problems and Solutions