背景:
我有一個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 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秒左右逾時.
标簽:android,bluetooth-lowenergy,android-bluetooth
來源: https://codeday.me/bug/20190706/1397909.html