Android BLE重新连接非常慢

背景:

我有一个BLE外设有两种模式:“应用程序”和“引导程序”.在这两种模式下,设备都使用相同的MAC地址进行通告.

要从一种模式切换到另一种模式,BLE外设必须自行重启.在这样做时,它必须断开任何活动的BLE连接.

BLE外设仅在Bootloader模式下保持约5秒钟.如果没有人在该窗口内连接它,它将切换到应用程序模式.

问题:

Android需要很长时间才能重新连接到BLE设备,足够长,以至于我错过了5秒窗口.原始代码有几层到BluetoothGATT和BluetoothAdapter层,但调用顺序归结为:

BluetoothGattCharacteristic c = mCharacteristics.get(POWER_STATE_UUID);
c.setValue(SHUTDOWN_VALUE);
mBluetoothGatt.writeCharacteristic(c);
// Signalled by BluetoothGattCallback.onCharacteristicWrite
bleWriteCondition.await();

mBluetoothGatt.disconnect();
// Wait for the underlying layer to confirm we're disconnected
while( mConnectionState != BluetoothProfile.STATE_DISCONNECTED ) {
    // Signalled by BluetoothGattCallback.onConnectionStateChange
    bleStateCondition.await(); 
}
mBluetoothGatt.connect();
while (mConnectionState != BluetoothProfile.STATE_CONNECTED) {
    // Signalled by BluetoothGattCallback.onConnectionStateChange
    bleStateCondition.await();
    if (bleStateCondition.stat != 0) {
        break;
    }
}

我完全是错误的做法吗?我试过在BluetoothGatt实例上调用close(),然后使用BluetoothDevice.connectGatt生成一个新的实例,但是我得到了同样非常慢的行为.

我正在测试三星Galaxy S4,API级别21.

最佳答案 这里的问题是gatt connect调用发出后台连接请求.此调用可能需要相当长的时间才能生成连接.这两种连接请求的描述如下: Direct vs Background connections

获得连接的绝对最快方式是进行扫描,并在找到设备时向其发出直接连接请求.当扫描刚刚找到它时,您知道它就在那里,连接将很快完成.这比您的示例代码更复杂,但是在您的小窗口的情况下最有效.扫描是查找设备最积极的方式.但是,如果您已有设备对象,则只需在设备上调用直接连接请求即可.

扫描是使用以下代码发出的:

scanner = bluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .build();
filters = new ArrayList<ScanFilter>();
ScanFilter uuidFilter = new ScanFilter.Builder()
            .setServiceUuid(YOUR_SERVICE_UUID).build();
filters.add(uuidFilter);
scanner.startScan(filters, settings, myScanCallback);

找到您的设备(使用扫描回调)后,通过此方法调用发出直接连接请求:

myGatt = myDevice.connectGatt(this, false, myGattCallback);

关键部分是false的参数.如果找不到设备,连接请求将在30秒左右超时.

点赞