Android BLE 讀寫開發(fā)回顧
這里主要記錄BLE的通訊方面的筆記
1.發(fā)現(xiàn)BluetoothGattService回調(diào)
BLE 調(diào)用gatt.connect()連接成功之后調(diào)用:
gatt.discoverServices()
觸發(fā)回調(diào)void onServicesDiscovered(BluetoothGatt gatt, int status)
通過硬件規(guī)定的uuid獲取對應(yīng)的BluetoothGattService:
BluetoothGattService service = gatt.getService(mServiceUuid);
在BluetoothGattService中包含一個或多個BluetoothGattCharacteristic,這些特征字將是后續(xù)用來讀寫數(shù)據(jù)的載體,而
通過硬件給定的uuid篩選出對應(yīng)的特征字,譬如有些特征字用于收發(fā)簡單命令,而有些特征字用于批量發(fā)送數(shù)據(jù):
if (characteristic.getUuid().equals(UUID.fromString(String.format(MEDTRUM_BASE_UUID, MEDTRUM_UUID_CHARACTERISTIC_BULK)))) {
//獲取批量發(fā)送數(shù)據(jù)特征字
mBulkCharacteristics = characteristic;
} else if (characteristic.getUuid().equals(UUID.fromString(String.format(MEDTRUM_BASE_UUID, MEDTRUM_UUID_CHARACTERISTIC_CTRLPT)))) {
//獲取收發(fā)命令特征字
mCommandCharacteristics = characteristic;
}
在拿到特征字之后并不能直接使用,如果特征字具有通知功能,那么還需要對其進行設(shè)置:
Log.d(TAG, "setCharacteristicNotification: "+gatt.setCharacteristicNotification(characteristic, true));
當(dāng)然,這還不夠,你會發(fā)現(xiàn)這個特征字可以正常的發(fā)送數(shù)據(jù),但是接受不到返回數(shù)據(jù),劃重點,這里別忘了對特征字描述符BluetoothGattDescriptor進行設(shè)置:
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
} else if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
設(shè)置描述符調(diào)用了mBluetoothGatt.writeDescriptor(descriptor)方法,對應(yīng)的回調(diào)為:
void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
在回調(diào)中可以對對應(yīng)的描述符進行驗證是否設(shè)置成功,然后就可以正常的使用特征字收發(fā)命令了;
注意,通常BluetoothGattService并不只包含一個特征字,而對特征字的設(shè)置動作底層其實也是一個寫的命令,理論上也會觸發(fā):
void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
但是在開發(fā)過程中通常并不能在這一步接收到回調(diào),這里的原因我還不是很清楚,大??吹秸垼瑹┱堉更c一二,嘻嘻。
既然是寫的操作,就必須遵循串行操作的原則,有序的寫,設(shè)置一個特征字之后延遲一段時間,再設(shè)置下一個。
這里的延遲時間比較講究,Android手機廠家眾多,所以需要給定的延遲時間也各不相同,開發(fā)經(jīng)驗發(fā)現(xiàn)如果間隔時間超過250ms SAMSUNG 2s內(nèi)連接不上會被動斷開,最終測試結(jié)果定在了700ms,可以適配目前所有的測試機型,如果有大牛有更好的解決辦法,煩請指點一二,嘻嘻。
2.讀寫數(shù)據(jù)
在拿到了特征字之后,就可以進行讀寫操作了,寫:
if (mCommandCharacteristics != null) {
if (value.length > 0) {
mCommandCharacteristics.setValue(value);
mBluetoothGatt.writeCharacteristic(mCommandCharacteristics);
}
}
發(fā)送數(shù)據(jù)之后,可以通過回調(diào):
onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
接收反饋,判斷命令是否發(fā)送成功。
對于數(shù)據(jù)的讀取,通過回調(diào):
void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
來獲取到反饋的內(nèi)容,可以看到這個回調(diào)中包含了特征字BluetoothGattCharacteristic很顯然,我么您可以通過特征字的uuid來判斷反饋的數(shù)據(jù)是命令返回,或者是通知消息;
注意,在讀寫交互中,請一定遵守串行傳輸?shù)臏?zhǔn)則,有序的收發(fā)命令,避免出現(xiàn)奇奇怪怪的bug;