Android BLE - Connecting to multiple devices at once

17,214

Solution 1

Indeed it is possible to connect to more than one peripheral from your Android device. However, it will make your code much more complex since you will need to manage each connection and responses.

For each connection you would have to implement a BluetoothGatt with it's callbacks. I tested it many months ago with a dummy test and as I said, it worked well and I was able to connect to different peripherals. However, if you chain many commands there seem to be some overlapping issues described in this thread.

Solution 2

As asked here is the relevant code : (Here the ArrayList contains the founded peripheral devices)

for(int i=0;i< Utility.selectedDeviceList.size();i++) {
            Log.d(Utility.TAG,"state"+ Utility.selectedDeviceList.get(i).getmConnectionState());
            if (Utility.selectedDeviceList.get(i).getmConnectionState() != Utility.CONNECTED) {
                Log.d(Utility.TAG,"Connecting LeSerive::" + Utility.selectedDeviceList.get(i).getAddress());
                Utility.mBluetoothLeService.connect(i, Utility.selectedDeviceList.get(i).getAddress());
            }

        }

This for loop is a part of runnable interface which is called inside a handler having a looper.

public void run() {
    Looper.prepare();
    Looper mLooper = Looper.myLooper();
    Log.d(Utility.TAG,"BLE Thread Started::");
    mHandler = new Handler(mLooper) {

        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case Utility.BLE_SYNC:
                    Log.d(Utility.TAG,"BLE Sync Connecting::");
                    mHandler.post(SynState);
                    break;
       }
    };
    Looper.loop();
}

I used this approach because their is lot of communication between peripherals to send and receive the data from them.

This is the connect method which inside a Service :

public boolean connect(int tag,final String address) {
    if (mBluetoothAdapter == null || address == null) {
        Log.w(Utility.TAG, "BluetoothAdapter not initialized or unspecified address.");
        return false;
    }

    Utility.selectedDeviceList.get(tag).setmConnectionState(Utility.CONNECTING);

    if( Utility.selectedDeviceList.get(tag).getmBluetoothGatt()==null){
        Log.w(Utility.TAG, "new connect :: "+ Utility.selectedDeviceList.get(tag).getAddress());

        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(Utility.TAG, "Device not found.  Unable to connect.");
            return false;
        }
        try {
            Utility.selectedDeviceList.get(tag).setmBluetoothGatt(device.connectGatt(this, false, mGattCallback));
        }
        catch (Exception e)
        {
            e.printStackTrace();
            Log.d(Utility.TAG,"ConnectGatt exception caught");
        }
    }

    return true;
}

This is the mGattCallBack :

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.d(Utility.TAG, "onServicesDiscovered");

    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {


    }
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
                                      BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        Log.d(Utility.TAG,">>onCharacteristicWrite");

    }
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {

    }
};

Hope it clears few things for you

Share:
17,214
Razgriz
Author by

Razgriz

An accomplished Software Developer and Engineer with a deep understanding of disruptive technologies and innovations such as Embedded Systems, Internet of Things, Artificial Intelligence, Computer Vision.

Updated on July 26, 2022

Comments

  • Razgriz
    Razgriz almost 2 years

    I am developing an Android Application that connects to a BLE Device and reads the Gatt Services and Gatt Characteristics. I used the BluetoothLeGatt sample project from the Android Development Site as my reference.

    So far, I am able to programmatically connect to a device (I took note of my Device's Address to be able to do this) and filter out the specific Gatt Service I want to read and that Services' specific Characteristics by taking note of the UUID of both the Service and the Characteristics. The sample provided by Google also updates whenever there's a message sent from my BLE Device to my Android Application. Overall, I have no problems at this end.

    However, upon reading up further on GATT, I found that it is possible to connect to multiple BLE devices (all slaves OR servers - being the ones that send the data) using a single Android Application (as master OR client - as the one who receives said data). So what I tried to do was to have 2 BLE Devices (different Address), took note of their Address, and then my application tries to connect to them once the application sees that those 2 addresses are up and running.

    In code, I call this function when I see my 2 BLE Devices:

    private void connectToDevice(){
    
        mDeviceName = deviceList.get(currentIndex).getName();
        mDeviceAddress = deviceList.get(currentIndex).getAddress();
    
        Log.e(TAG, "connecting to device name = " + mDeviceName);
    
        mBluetoothLeService.connect(mDeviceAddress);
    }
    

    Where currentIndex is initially set to zero. Then once I get a successful connection, I do:

    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
                Log.e(TAG, "connected");
                mConnected = true;
    
                if(currentIndex < deviceList.size()-1) currentIndex ++;
                connectToDevice();
    
            } 
        }
    };
    

    Where I check if I still have devices to connect to in my deviceList, if so, increment my counter and then connect until I exhaust everything in my list.

    However, I seem to have no success at all using this method.

    Kindly note that switching connection (round robin) between my devices isn't an option. This will be an issue when I have a lot of devices and it's important to get their messages real time without delays. This said, I have to have a live connection to my devices.

    Has anyone tried to connect to multiple BLE Devices in Android? I'm not sure on how to proceed on this.

  • Razgriz
    Razgriz over 8 years
    Would you happen to still have your code from many months ago? To be honest, all I do is to wait for messages from my devices and I don't actually have to send out messages yet so I won't have worries about chaining commands.
  • GoRoS
    GoRoS over 8 years
    Unfortunately no, it was a quick PoC for a work project and once I tested and proved it, due to it's simplicity it went to straight to trash.
  • Razgriz
    Razgriz over 8 years
    Tough luck for me then. Would you recall if you used an individual BluetoothLeService for each device you had to connect to? Or did you just use multiple BluetoothGatt and handled their callbacks individually?
  • GoRoS
    GoRoS over 8 years
    Sure, I developed multiple BluetoothGatt instances per connection and handled their callbacks individually.
  • Razgriz
    Razgriz over 8 years
    Much appreciated. I will most probably share my answer here when I get it working.
  • Razgriz
    Razgriz over 8 years
    I attempted to do multiple connections, handlers, and callbacks to try and connect to my 2 devices a the same time. However, it does not seem to work. I posted a new question about it here: stackoverflow.com/questions/35406168/… and it would help if you can take a look at my code there. Thank you!
  • Razgriz
    Razgriz over 8 years
    I attempted to do multiple connections, handlers, and callbacks to try and connect to my 2 devices a the same time. However, it does not seem to work. I posted a new question about it here: stackoverflow.com/questions/35406168/… and it would help if you can take a look at my code there. Thank you!