I have a bluetooth headset which is paired with my Nexus 5X (running Android 7.1) and I would like to connect to a GATT Server of the headset. I tried it with the following code:
private BluetoothGattCallback btleGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.d(TAG, "onConnectionStateChange: " + status + ", " + newState);
if(newState == STATE_CONNECTED) {
Log.d(TAG, "Device connected");
boolean ans = gatt.discoverServices();
Log.d(TAG, "Discover Services started: " + ans);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.d(TAG, "Number of Services: " + gatt.getServices().size());
}
};
public void onDeviceClicked(BluetoothDevice device) {
BluetoothGatt gatt = device.connectGatt(this, false, btleGattCallback);
Log.d(TAG, "Connected to GATT: " + gatt.connect());
}
If I click on the headset in my UI onDeviceClicked
is called and it comes to this Log output:
<!-- language: lang-none -->
Connected to GATT: true
onConnectionStateChange: 0, 2 // GATT_SUCCESS, STATE_CONNECTED
Device connected
Discover Services started: true
As you can see onServicesDiscovered
is never fired. I tried to call connectGatt
with TRANSPORT_LE
(ref) but then I get a onConnectionStateChange: 133, 0
. I also found this question which is why I added the gatt.connect()
method as mentioned in answer two.
Do you have any ideas why I don't get the onServicesDiscovered
callback?
Something that has been really useful for me is to wait for about 600ms after the connection has been established and then start the service discovery.
BLE on Android can be a little finicky.
Make sure you are calling mBluetoothGatt.discoverServices() on the UI thread.
if(newState == STATE_CONNECTED) {
Log.d(TAG, "Device connected");
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
boolean ans = mBluetoothGatt.discoverServices();
Log.d(TAG, "Discover Services started: " + ans);
}
});
}
Also try making BluetoothGatt gatt
a field variable instead of a local variable.
If you are doing any significant work, try using a library that masks all of the idiosyncrasies so you can focus on the high level logic. https://github.com/Polidea/RxAndroidBle.
Here is an example of how to read a characteristic.
connectionObservable
.flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(characteristicUuid))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bytes -> {
readOutputView.setText(new String(bytes));
readHexOutputView.setText(HexString.bytesToHex(bytes));
writeInput.setText(HexString.bytesToHex(bytes));
}, this::onReadFailure);
Or with Java 7 syntax
connectionObservable
.flatMap(new Func1<RxBleConnection, Observable<byte[]>>() {
@Override
public Observable<byte[]> call(RxBleConnection rxBleConnection) {
return rxBleConnection.readCharacteristic(characteristicUuid);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<byte[]>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
onReadFailure(e);
}
@Override
public void onNext(byte[] bytes) {
readOutputView.setText(new String(bytes));
readHexOutputView.setText(HexString.bytesToHex(bytes));
writeInput.setText(HexString.bytesToHex(bytes));
}
});
Had the same problem, but waiting 600 ms wasn't enough. This is probably due to the BLE module used. I fixed the problem by calling my method
discoverServices();
after calling
device.connectGatt(this,false,gattCallback)
I'm basically just calling discoverServices every 5 seconds (this is arbitrarily chosen)
private void discoverServices() {
if(!gattConnected) { //just a boolean
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
gatt.discoverServices();
}
});
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
discoverServices();
}
}, 5000);
}
}
In the onServicesDiscovered(...) method of my gattCallback I make gattConnected true. This worked for me.
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