摘要:連接回調(diào)連接成功連接斷開改變當前狀態(tài)當服務發(fā)現(xiàn)之后回調(diào)這里四發(fā)現(xiàn)服務一個低功耗藍牙設(shè)備是有很多種服務的,就比如該設(shè)備的電量信息,設(shè)備的當前狀態(tài)比如血壓計是正在測量還是在等待測量有的設(shè)備支持歷史數(shù)據(jù)等等。
一、檢測本機是否支持藍牙????公司開發(fā)任務是,將醫(yī)療設(shè)備通過藍牙集成到app中,在這開發(fā)中遇到了數(shù)不盡的坑.在此記錄一下做一個記錄,如果其他開發(fā)人員看見或許能提供一些幫助,如有不對,盡情指正,不勝感激!
??剛開始接觸的時候,被各種超長的API嚇到了,像:BluetoothGatt , BluetoothGattCharacteristic , BluetoothGattDescriptor 等等.而且還要做多連接,上位機一對多下位機.網(wǎng)上例子也是雜七雜八.看的頭暈.后來在老大的幫助下,漸漸明白許多,在此感謝老大.廢話到此結(jié)束,下面進入正題.
1. 判斷當前設(shè)備是否支持藍牙
BluetoothManager mBluetoothManager = (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter adapter = mBluetoothManager.getAdapter(); if(adapter==null){ //系統(tǒng)不支持藍牙。 }
2. 判斷當前設(shè)備是否支持低功耗藍牙BLE
boolean isSupportBle = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
3. 判斷藍牙是否開啟,開啟藍牙!
BluetoothManager mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter adapter = mBluetoothManager.getAdapter(); if(!adapter.isEnable){ //未開啟藍牙 //申請開啟藍牙 Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(intent , request); }二、開始掃描周圍的藍牙設(shè)備
BluetoothAdapter adapter = mBluetoothManager.getAdapter(); adapter.startLeScan(callback); //掃描需要一個回調(diào)。
注意,掃描周圍藍牙是一個很耗電的過程,最好加上一個掃描時間。自動停止。
handler.postDelayed(new Runnable() { @Override public void run() { adapter.stopLeScan(callback); //停止掃描 } },10000);//設(shè)置10秒鐘結(jié)束掃描
public BluetoothAdapter.LeScanCallback scanCallBack = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { //這里注意,本人在開發(fā)中遇到的是 經(jīng)常有的藍牙設(shè)備是沒有名字的, (device.getName == null) //不知道這是什么原因引起的,后來跟很多藍牙高手討論的是結(jié)果初步懷疑應該是芯片的問題 //尤其是MTK的芯片經(jīng)常出現(xiàn)這種問題,換了搭載高通和華為的芯片的設(shè)備就沒問題了。 } };三、連接藍牙設(shè)備
BluetoothDevice remoteDevice = adapter.getRemoteDevice(address); remoteDevice.connectGatt(context, true, mGattCallback);//參數(shù)1:上下文。 //參數(shù)2:是否自動連接(當設(shè)備可以用時) //參數(shù)3:連接回調(diào)。
這里可能有些疑問就是,明明已經(jīng)掃描到了,在回調(diào)中已經(jīng)有了 BluetoothDevice 為何還要去 getRemoteDevice(address)?
那是因為,很多低功耗的設(shè)備開機時間是很少的,就拿我們公司開發(fā)的那個血壓計,他是開機才開啟藍牙,而測量完了之后過一段時間就會自動關(guān)閉。所以防止去連接設(shè)備的時候設(shè)備已經(jīng)關(guān)機的情況。
連接回調(diào)
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { //連接成功 } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { //連接斷開 } changeStatus(newState);//改變當前狀態(tài) } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { //當服務發(fā)現(xiàn)之后回調(diào)這里 } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { } };四、發(fā)現(xiàn)服務
一個低功耗藍牙設(shè)備是有很多種服務的,就比如該設(shè)備的電量信息,設(shè)備的當前狀態(tài)(比如血壓計,是正在測量還是在等待測量)
有的設(shè)備支持歷史數(shù)據(jù)等等。這些都是在藍牙的服務當中。我們要去發(fā)現(xiàn)藍牙的服務!
這里很簡單就是一句話,在連接成功的回調(diào)中調(diào)用:
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { //連接成功 gatt.discoverServices();//開始發(fā)現(xiàn)設(shè)備的服務 } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { //連接斷開 } changeStatus(newState);//改變當前狀態(tài) }
調(diào)用了之后會在 另一個回調(diào)中 回調(diào)回來。
@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { //當服務發(fā)現(xiàn)之后回調(diào)這里 }五、數(shù)據(jù)交互
這里是比較重要的地方,注意,每一個藍牙的通訊協(xié)議不通,有的設(shè)備是連接了之后不需要任何操作就等待藍牙設(shè)備上傳數(shù)據(jù)的,而有的設(shè)備是需要手動打開數(shù)據(jù)通道!或者發(fā)送指令給藍牙設(shè)備,每一個Gatt協(xié)議中有多個BluetoothGattService,而每個BluetoothGattService中又有多個BluetoothGattCharacteristic (我把它看做一個數(shù)據(jù)通道-_-!),而每一個BluetoothGattCharacteristic 的屬性是不同的,有的是可讀,有的是可寫,有的是可訂閱,所以一定不要搞混了,可以用UUID區(qū)分他們,這里大多數(shù)設(shè)備廠家都會給一份設(shè)備的通訊協(xié)議其中就有 哪一個UUID 代表什么。都會有說明。通過UUID 獲取到了對應的BluetoothGattCharacteristic 之后就可以判斷他的屬性是什么。
開啟數(shù)據(jù)通道
@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { //服務發(fā)現(xiàn)方法回調(diào)。 if (status == BluetoothGatt.GATT_SUCCESS) { BluetoothGattService service = gatt.getService(SERVICE_UUID); //通過廠家給的UUID獲取BluetoothGattService if (service != null) { BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHARACTERISTIC_UUID);//同上 if (characteristic != null && (characteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { //通過判斷,打開Notification 通知,提醒。一般是設(shè)備測量完成了之后會發(fā)送對應的數(shù)據(jù)上來。 gatt.setCharacteristicNotification(characteristic, true); //在通過上面的設(shè)置返回為true之后還要進行下面的操作,才能訂閱到數(shù)據(jù)的上傳。下面是完整的訂閱數(shù)據(jù)代碼! if(gatt.setCharacteristicNotification(characteristic, true)){ for(BluetoothGattDescriptor dp: characteristic.getDescriptors()){ if (dp != null) { if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) { dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); } else if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) { dp.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); } gatt.writeDescriptor(dp); } } } } } } }
像設(shè)備發(fā)送指令
??一般向設(shè)備發(fā)送什么指令在通訊協(xié)議上面也是有的,都是發(fā)送一個byte[]數(shù)組,每一位代表什么協(xié)議里面都是不同的。例如:一個測量溫度的設(shè)備,他當前是華氏度的單位,我們可以給他發(fā)送一個指令讓他把單位更換成攝氏度:
private void changeMonitorMod(BluetoothGatt gatt, byte[] buffer) { if (gatt != null && gatt != null) { BluetoothGattService writeService = gatt.getService(MYUUID); if (writeService == null) { return; } } BluetoothGattCharacteristic writeCharacteristic = writeService.getCharacteristic(MYWRITECHARACTERISTIC); if (writeCharacteristic == null) { return; } writeCharacteristic.setValue(buffer); //上面的buffer數(shù)組中裝的就是指令,多長? 每一位上面的數(shù)字代表什么意思在協(xié)議中查看! gatt.writeCharacteristic(writeCharacteristic);//像設(shè)備寫入指令。 }
不要忘了,要在清單文件中AndroidManifest.xml 聲明權(quán)限哦。
關(guān)于一些坑:
很多廠家很坑爹,給的文檔水的要命,第一時間要看看文檔詳細不詳細,如果沒有文檔至少也要給個Demo.
注意設(shè)備的開機時間,自動關(guān)機時間,對狀態(tài)的保存。
很多設(shè)備在自動關(guān)機之后的回調(diào)是很慢的,甚至設(shè)備關(guān)機10秒之后才會回調(diào)到連接狀態(tài)的回調(diào)方法中。
關(guān)于手動設(shè)置斷開 gatt.disConnect() 這個方法,我試過了,調(diào)用之后確實會立即回調(diào)到對應的狀態(tài)方法中,但是實際上物理上的連接是還沒有斷開的。物理上的連接斷開之后還會再次回調(diào)到方法中。這是一個比較漫長的回調(diào),區(qū)別與設(shè)備,不通設(shè)備的機制不一樣,有的快,有的慢。
??好了,差不多就這么多,寫的匆忙,如果有哪里不對,輕噴,還請大佬們指正。謝啦!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/66441.html
摘要:更新修正協(xié)議下默認關(guān)閉時會取消訂閱本次訂閱的所有物聯(lián)網(wǎng)整體方案篇年,云巴利用實時跨平臺雙向物聯(lián)網(wǎng)云端系統(tǒng)的產(chǎn)品優(yōu)勢,積極迎接物聯(lián)網(wǎng)新時代,為客戶定制物聯(lián)網(wǎng)整體解決方案。 SDK 篇 Android SDK 更新 ·Android Release 1.8.5在demo中去除掉小米、華為平臺的jar包,讓用戶自行下載 ·Android SDK 1.8.6對新版華為推送做了適配。 JavaS...
閱讀 2746·2021-10-11 10:57
閱讀 1574·2021-09-26 09:55
閱讀 1314·2021-09-06 15:11
閱讀 3454·2021-08-26 14:16
閱讀 671·2019-08-30 15:54
閱讀 541·2019-08-30 12:43
閱讀 3297·2019-08-29 16:18
閱讀 2573·2019-08-23 16:14