Android ble藍牙問題(轉)


Android ble藍牙問題

(1)藍牙回調
安卓4.4的藍牙回調是在異步線程中(不在主線程),若要在藍牙回調中執行更新界面的操作,記得切換到主線程去操作

 

 

(2)三星手機兼容性問題
connectGatt()方法在某些三星手機上只能在UI線程調用。

備注:三星的手機是connet和disconnet還有connectGatt都要在UI線程中操作

 

 

(3)Android L 新API
Android L換了一套掃描設備的API:BluetoothLeScanner.startScan(List, ScanSettings, ScanCallback)

 

 

(4)Android M新的權限(android 6.0 動態權限)
Android M中必須擁有定位權限才能掃描BLE設備

 

(4)連接不斷開的問題
別的BLE程序非法保留連接的設備可能會導致連接不能斷開

 

(5)異步問題
讀寫Characteristic、Descriptor等幾乎所有BLE操作結果都為異步返回,若不等待上一次操作結果返回就執行下一次操作,很可能導致操作失敗或者操作無效。onDescriptorWrite()返回的線程與寫入線程為同一個線程,別的操作一般在不同的線程回調。

 

 

(6)設備緩存
Android會對連接過的BLE設備的Services進行緩存,若設備升級后Services等有改動,則程序會出現通訊失敗。此時就得刷新緩存,但是刷新緩存的方法並沒有開放,這里只能使用反射來調用BluetoothGatt類中的refresh()方法:

復制代碼
1 try {
2   Method localMethod = mBluetoothGatt.getClass().getMethod("refresh");
3   if (localMethod != null) {
4       return (Boolean) localMethod.invoke(mBluetoothGatt);
5   }
6 } catch (Exception localException) {
7   Log.e("refreshServices()", "An exception occured while refreshing device");
8 }
復制代碼

 

(7)掃描設備
startLeScan(UUID[], BluetoothAdapter.LeScanCallback)

在Android4.4及以下手機中似乎只支持16位的短UUID,不支持128位完整的UUID。

(9)任何出錯,超時,用完就馬上調用Gatt.disconnect(), Gatt.close()。

(10)從bindService 到 onServiceConnected 這個回調花費時間較長, onServiceConnected 這個回調很可能在 MainActivity onResume之后才執行, 所以不要指望onResume里去執行掃描,因為此時serviceConnected 回調都尚未執行

(11)getBtAdapter().enable()是異步,立即返回,但從 off 到 on 的過程需要一個時間所以只能監聽系統broadcast發出的intent里的state

12) 多次掃描藍牙,在華為榮耀,魅族M3 NOTE 中有的機型,會發現多次斷開–掃描–斷開–掃描… 會掃描不到設備,此時需要在斷開連接后,不能立即掃描,而是要先停止掃描后,過2秒再掃描才能掃描到設備。

(13)掃描盡量不要放在主線程進行,可以放入子線程里。不然有些機型會出現 do too many work in main thread.

(14)設備的gatt在不用時要及時關閉,系統支持的連接句柄數是有限的,當達到上限后無法再建立新的連接了。

(15)當連接斷開后要調closeGatt釋放資源,不用調disconnect,也不要下次復用之前的gatt來reconnect,因為有的手機上重連可能會存在問題,比如重連后死活發現不了service。這種情況下,最好只要斷開連接就close gatt,下次連接時打開全新的gatt,這樣就可以發現service了。

(16)BLE的特征一次讀寫最大長度20字節。

 (17)一個主設備(例如Android手機)可以同時連接多個從設備(一般為6個,例如智能硬件。超過就連接不上了),一個從設備只能被一個主設備連接,一旦從設備連接上主設備,就停止廣播,斷開連接則繼續廣播。在任何時刻都只能最多一個設備在嘗試建立連接。如果同時對多個藍牙設備發起建立Gatt連接請求。如果前面的設備連接失敗了,則后面的設備請求會被永遠阻塞住,不會有任何連接回調。所以建議:如果要對多個設備發起連接請求,最好是一個接一個的順序同步請求管理。

(18)對藍牙設備的操作不能並行,只能串行,即每次都要在收到上一個操作的回調后才能繼續下一個操作。但是斷開連接例外,斷開連接要馬上closeGatt,不用等任務隊列中的其他操作了。而且要給所有正在執行或者准備執行的任務都cancel。

(19)有時候藍牙協議棧出現異常可能收不到回調,所以我們要對每個操作做超時檢查,否則后面的所有操作都被阻塞了。

(20)對於超時的任務,最好closeGatt,下次重新連接的時候重開一個gatt。

(21)藍牙連接可能不穩定,最好支持失敗自動重試機制,尤其是連接和發現服務,因為80%的問題都發生在建立連接和發現服務的時候,而且這一塊也是最耗時的。

(22)Android 從 4.3(API Level 18) 開始支持低功耗藍牙,但是只支持作為中心設備 (Central) 模式,這就意味着 Android 設備只能主動掃描和鏈接其他外圍設備 (Peripheral)。從Android 5.0(API Level 21)開始兩種模式都支持。BLE 官方文檔在  這里 。 

(23)

在  BluetoothAdapter.startLeScan() 的時候,在 BluetoothAdapter.LeScanCallback.onLeScan() 中不能做太多事情,特別是周圍的BLE設備多的時候,非常容易導致出現如下錯誤: 

 

E/GKI  LINUX(17741): ##### ERROR : GKI exception: GKI  exception(): Task State Table E/GKI LINUX(17741): ##### 

E/GKI  LINUX(17741): ##### ERROR : GKI exception: TASK ID [0] task name [BTU] state [1] 

E/GKI 

LINUX(17741): #####

LINUX(17741): ##### ERROR : GKI 

exception: TASK ID [1] task name [BTIF] state [1]

LINUX(17741): ##### 

 

E/GKI  LINUX(17741): ##### ERROR : GKI exception: TASK ID [2] task name [A2DP-MEDIA] state [1] 

E/GKI 

LINUX(17741): #####

LINUX(17741): ##### ERROR : GKI   exception: GKI exception 65524 getbuf: out of buffers##### 

 

E/GKI  LINUX(17741): ##### ERROR : GKI exception: 

E/GKI_LINUX(17741):  * * * * * * * * * * * * * * * * * * * * * * 

開發建議:在  onLeScan() 回調中只做盡量少的工作,可以把掃描到的設備,扔到另外一個線程中去處理,讓  onLeScan() 盡快返回。  [  參考帖子 ] 

(24)BLE 設備的建立和斷開連接的操作,例如 BluetoothDevice.connectGatt() ,  BluetoothGatt.connect() , BluetoothGatt.disconnect() 等操作最好都放在主線程中,否則你會遇到很多意想不到的麻煩。 

開發建議:對  BluetoothGatt 的連接和斷開請求,都通過發送消息到 Android 的主線程中,讓主線程來執行具體的操作。例如創建一個  new Handler(context.getMainLooper()); ,把消息發送到這個  Handler中。  [  參考帖子 ] 

 (25)

如果你在開發 BLE 應用的時候,有時候會發現系統的功耗明顯增加了,查看電量使用情況,藍牙功耗占比非常高,好像低功耗是徒有虛名。使用  adb bugreport 獲取的了系統信息,分析發現一個名叫 BluetoothRemoteDevices 的  WakeLock 鎖持有時間非常長,導致系統進入不了休眠。分析源代碼發現,在連接 BLE 設備的過程中,系統會持有 (Aquire) 這個  WakeLock ,直到連接上或者主動斷開連接(調用  disconnect() )才會釋放。如果BLE設備不在范圍內,這個超時時間大約為30s,而這時你可能又要嘗試重新連接,這個  WakeLock 有被重新持有,這樣系統就永遠不能休眠了。 

開發建議:對BLE設備連接,連接過程要盡量短,如果連接不上,不要盲目進行重連,否這你的電池會很快被消耗掉。這個情況,實際上對傳統藍牙設備連接也是一樣。  [  參考帖子 ] 

(26)

Android 作為中心設備,最多只能同時連接 6 個 BLE 外圍設備(可能不同的設備這個數字不一樣),超過 6 個,就會連接不上了。現在 BLE 設備越來越多,其實並不夠用,所以在開發的過程中,需要特別的謹慎使用。

開發建議:按照需要連接設備,如果設備使用完了,應該馬上釋放連接(調用 BluetoothGatt.close() ),騰出系統資源給其他可能的設備連接。  [  參考帖子 ] 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM