2
votes

I have started to developing android application newly. I have exact same devices with different MAC Address, and I need to discover services, characteristics and read the data, at the same time or respectively. The Devices must be paired with the tablet or phone in my use-case. I can connect to BluetoothGatt and get BluetoothGattCalback, and I can discover services, characteristics and read the data. If I pair two or more devices I can only discover the services of one device. While I am listing the services I am writing the devices' MAC Address to know which service belongs to which device. This is my BluetoothGattCalback :

    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        String intentAction;
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_CONNECTED;
            broadcastUpdate(intentAction);
            Log.i(TAG, "Connected to GATT server.");
            // Attempts to discover services after successful connection.
            Log.i(TAG, "Attempting to start service discovery:" +
                    mBluetoothGatt.discoverServices());
            try{
                mBluetoothGatt.wait(1000);
            }catch (Exception e){

            }

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            intentAction = ACTION_GATT_DISCONNECTED;
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server.");
            broadcastUpdate(intentAction);
            //mBluetoothGatt.disconnect();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
        } else {
            Log.w(TAG, "onServicesDiscovered received: " + status);
        }
        //mBluetoothGatt.disconnect();

    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic,
                                     int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }
        mBluetoothGatt.disconnect();

    }

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

Below code is how I connect to gatt :

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    for (BluetoothDevice bd:mBluetoothAdapter.getBondedDevices()
         ) {
        mBluetoothGatt=bd.connectGatt(this,false,mGattCallback);
        try{
            Thread.sleep(250);
        }catch(Exception e){

        }
    }

I tried to increase Thread.sleep(250) to 500-1000-2000 nothing changed. Maybe I don't know how to loop properly to connect gatt for each device.

Note: Sometimes services are discovered and listed doubled for two devices but the listed device MAC Address is all same.

Important Note: I don't want to construct more than one BluetoothGattCalback and BluetoothGatt, because device count may change in any case.

Any help would be appreciated. Thanks.

EDIT:

Above issue is solved by making the Override methods of BluetoothGattCallback synchronized and using the inner BluetoothGatt parameter instead of global one as @Emil mentioned. But it brought me all new problem:

If I don't restart my BLE Devices, It doesn't connect to GATT Server after discovering services, even I restart program.

1
Thread.sleep is not a solution for this. use Handler.postdelayed method to delay the next call to connectgatt. Thread.sleep will pause u r thread execution and u wont even receive mGattCallback for starting service discovery.siva
@7383 thanks for reply, I am a little bit confused, where to use Handler.postdelayed? I am newbie to android.Alican Uzun
use this code. set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices(); int n=0; Handler handler = new Handler();//make sure u r executing this code on mainthread Runnable runnable = new Runnable(){ void run(){ mBluetoothGatt=bd.connectGatt(this,false,mGattCallback); } }; //copy the below code wherver u wanted connect the gatt. for (BluetoothDevice bd:devices) { handler.postDelayed(runnable, n*2500); }siva
public void run(){ mBluetoothGatt=bd.connectGatt(this,false,mGattCallback); } on this part it says Cannot resolve symbol bdAlican Uzun
@7383 I fixed the problem, but it gives complicated results. And it makes the tablet's bluetooth device unworkable.Alican Uzun

1 Answers

1
votes

The problem is that you overwrite mBluetoothGatt in the second loop iteration. When you then call mBluetoothGatt.discoverServices() once the device connects, you execute discoverServices() on the wrong gatt object. Just use the gatt parameter directly instead of mBluetoothGatt.

And you should remove those sleep and wait calls.