Android Lollipop BLE 外围设备:调用 BluetoothLeAdvertiser.stopAdvertising(AdvertiseCallback) 与连接的中央设备断开连接

Android Lollipop BLE Peripheral: calling BluetoothLeAdvertiser.stopAdvertising(AdvertiseCallback) disconnects from connected central

我希望在中心连接(并订阅特定特征)时停止广告:

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);
    }
}

调用stopAdvertising()后,中央和外围断开 来自 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

随着 stopAdvertising() 的评论,与中央的连接(和通信)继续。

有没有人在 Android 的 BLE 外设实现中遇到过这个问题?在iOS中没有这个问题。

进入连接后不需要调用stopAdvertising

LE 控制器的 Link 层有 5 种状态:"Idle"、"Advertising"、"Scanning"、"Initiating" 和 "Connected"。

当您做广告时,您处于 "Advertising" 状态。当它连接时,它进入 "Connected" 状态。

最有可能的是,stopAdvertising 方法假定您在调用时处于 "Advertising" 状态,并且在不检查这一点的情况下,执行您在 [=26] 中调用它时应该执行的操作=]:进入"Idle"状态。

所以当你调用它时,无论当前状态如何,LL 都会进入 "Idle"。

这似乎是 Android 的 BLE 主机堆栈中的错误。当您在 "Connected" 状态下调用 stopAdvertising 时,正确的行为应该是 return 一个错误代码(例如 "Invalid state for this command")或者直接忽略。

Bogdan 的回答适用于蓝牙 LE 4.0。然而 4.1 外围设备可以连接到超过 1 个中央设备,因此外围设备决定是否要在建立连接后停止广播而不立即失去该连接是有意义的。这看起来像是 Android L 最近 5.1.1

中的错误