Android ble藍牙問題

 

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

 

 

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

備註:三星的手機是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設備ide

 

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

 

(5)異步問題
讀寫Characteristic、Descriptor等幾乎全部BLE操做結果都爲異步返回,若不等待上一次操做結果返回就執行下一次操做,極可能致使操做失敗或者操做無效。onDescriptorWrite()返回的線程與寫入線程爲同一個線程,別的操做通常在不一樣的線程回調。ui

 

 

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

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)spa

在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() ),騰出系統資源給其餘可能的設備鏈接。  [  參考帖子 ] 

相關文章
相關標籤/搜索