Reputation: 55
I wish to stop advertising when a central connects (and subscribes to a specific characteristic):
private final BluetoothGattServerCallback bleCallbacks = new BluetoothGattServerCallback() {
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value){
Log.v(DEBUG_TAG, "onDescriptorWriteRequest()...");
BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
Log.v(DEBUG_TAG, "----- characteristic: " + characteristic.getUuid().toString());
if (characteristic.equals(peripheralCharacteristic)){
descriptor.setValue(value);
if (bluetoothGattServer.sendResponse(device,
requestId,
BluetoothGatt.GATT_SUCCESS,
offset,
value)){
central = device;
stopAdvertising(); //causes disconnection
return;
}
}
bluetoothGattServer.sendResponse(device,
requestId,
BluetoothGatt.GATT_WRITE_NOT_PERMITTED,
0,
null);
}
...
}
private void stopAdvertising(){
if (bluetoothLeAdvertiser != null) {
bluetoothLeAdvertiser.stopAdvertising(advertiseCallback);
}
}
Upon calling stopAdvertising(), the central and peripheral disconnect from logcat:
04-01 11:26:06.179 7068-7085/package.Class﹕ onDescriptorWriteRequest()...
04-01 11:26:06.179 7068-7085/package.Class﹕ ----- characteristic: 80a1a1a5-8b5b-e88b-9d24-2e609654b852
04-01 11:26:06.207 7068-7085/package D/BluetoothGattServer﹕ onServerConnectionState() - status=0 serverIf=5 device=00:07:80:2F:0F:A2
With stopAdvertising() commented, connection (and communication) with the central continues.
Has anyone encountered this issue with Android's BLE Peripheral Implementation? In iOS, there is no such issue.
Upvotes: 2
Views: 1591
Reputation: 1
Bogdan's answer applies to Bluetooth LE 4.0. However 4.1 peripherals can connect to more than 1 central, so it makes sense for a peripheral to decide whether or not it wants to stop advertising once a connection is made without immediately losing that connection. This looks like a bug in Android L as recently as 5.1.1
Upvotes: 0
Reputation: 5542
You do not need to call stopAdvertising
after entering a connection.
The Link Layer from the LE Controller has 5 states: "Idle", "Advertising", "Scanning", "Initiating" and "Connected".
When you advertise, you're in "Advertising" state. When it connects, it goes into "Connected" state.
Most likely, the stopAdvertising
method assumes you are in "Advertising" state at the time of calling and, without checking this, does what it's supposed to do when you call it in "Advertising": it goes to "Idle" state.
So when you call it, the LL goes into "Idle" regardless of current state.
This seems like a bug in the BLE Host Stack from Android. The correct behaviour when you call stopAdvertising
in a "Connected" state should be to return an error code (e.g. "Invalid state for this command") or simply ignore.
Upvotes: 1