參考資料:https://github.com/Charon1997/BleCar
api5.0與之前版本的ble問題
主要參考:
搜索:MainActivity
連接:ControlActivity+BluetoothLeService
這次要做一個BLE的小功能,給一塊Nordic_UART的板子做對接。
先頭說要接入Nordic的sdk,後來找了BleCar的資料發現沒有必要,直接可以發現,和讀取。
在和我的ios同時對比中發現,ios發現後默認就可以讀出設備上的value,而Android則需要手動向設備發起查詢
參照上述參考資料可以順利完成連接,然後讀數難住了,
https://www.cnblogs.com/cxk1995/p/5693979.html
看了幾篇帖子,都大同小異,我不太明白髮送時的BluetoothGattCharacteristic是怎麼來的,畢竟發現的時候BluetoothGattCharacteristic可發現了五個,你讓我給誰發?
於是實踐出真知,關於收發的部分我修改了一下,在Service中提了一個characteristic的List,又包裝了兩個方法
public List<BluetoothGattCharacteristic> characteristics = new ArrayList<>();
public void writeCharacteristic(String msg){
Log.d(TAG, "writeCharacteristic has characteristics"+characteristics.size());
for(int i=0;i<characteristics.size();i++){
BluetoothGattCharacteristic cc = characteristics.get(i);
cc.setValue(msg);
writeCharacteristic(cc);
}
}
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
} else mBluetoothGatt.writeCharacteristic(characteristic);
}
public void readCharacteristic(){
Log.d(TAG, "readCharacteristic has characteristics"+characteristics.size());
for(BluetoothGattCharacteristic characteristic:characteristics){
readCharacteristic(characteristic);
}
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic){
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
} else mBluetoothGatt.readCharacteristic(characteristic);
}
讀取結果爲:
黃色爲readCharacteristic(),紅色爲writeCharacteristic(msg)
在onServicesDiscovered結束時,characteristics的個數一共是5個,打印log也能夠看出來,但最後能夠做讀取修改的只有一個,這個大概是和硬件設置有關,不能寫的也沒有回調。
另外還要說明一點,state=133的問題除了最初鏈接的時候發生過,在writeCharacteristic的數據過長時也發生了。
error code對照
ASCII對照表
關於Bluetooth包中類的一些解釋
android這邊調試ble的時候有幾個問題需要說明
1是不知道要給5個特徵裏哪一個發送,直到看了源碼發現:
if((gattCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)>0) {
//true爲符合讀寫條件的
}
這個判斷在write裏面也有,但是我不知道呀所以當時就循環發了。
2、是Android這邊由於google已經封裝好了不用像ios一樣先把string轉成16進制ascii碼再轉成NSDATA,我們這邊只要String或者String.getBytes()就搞定了
3、註冊監聽
當你給藍牙寫了一條數據之後,不用起timer輪詢readCharacteristic,直接註冊監聽在Gatta的CallBack裏等
onCharacteristicChanged被調用,然而我做的時候參考了大部分帖子都是這麼說的:
boolean isEnableNotification =
mBluetoothGatt.setCharacteristicNotification(characteristic, true);
Log.d(TAG, "Bluetooth setCharacteristicNotification:"+isEnableNotification);
//這裏是設置可接收的屬性,沒有下面這段onCharacteristicChanged不會被調用
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
請問SampleGattAttributes是個啥?
然後有看到人家說UUID_CCC,看了好幾篇帖子,覺得UUID_CCC是個固定的UUID:”00002902-0000-1000-8000-00805f9b34fb”
這個uuid的descriptor 是在characteristic裏面的,然而我write的characteristic.getDescriptors().size()=0一下就沒得玩了。
找了幾篇不錯的帖子解析帖子去說這個
在僵持不下之時我靈光一閃,我可是有三條service呀,會不會是其他service下的特徵有descriptor呢?於是通過輪詢我發現和write那條characteristic同級別的service裏另一條characteristic中有descriptor
於是打印發現descriptor uuid:00002902-0000-1000-8000-00805f9b34fb
眼熟不眼熟,然後修改了監聽的characteristic,這麼一運行,就返回來了
/BlueToothService: onCharacteristicChanged characteristic UUID:6e400003-b5a3-f393-e0a9-e50e24dcca9e characteristic:$LockOpened
4、發送順序
mBluetoothGatt.writeCharacteristic(characteristic);要先於mBluetoothGatt.setCharacteristicNotification
爲什麼我不清楚,但順序反了就接不到了╮(╯▽╰)╭
這裏還想說,有一本書叫《ANDROID物聯網開發從入門到實戰》裏面從第四章開始看就可以了,是講BLE藍牙的,比零散的博客更系統的講述BLE和傳統藍牙的不同,比如其中提到了BLE和NFC的對比,NFC達不到BLE的傳輸速度,雖然它的設置更簡化。
而我覺得比較有價值的是4.5章低功耗藍牙協議棧詳解