自從Android-BLE庫開源了一段時間以來,愈來愈多的小夥伴問到了各類各樣的關於BLE的奇怪問題,在這裏我想跟你們分享一下本人對於Android BLE藍牙的一些見解和解決方式,避免剛接觸的小夥伴再次踩坑。android
不少人曾問過我這個問題,爲何其餘手機都沒什麼問題,就華爲的一些手機總是鏈接不穩定,常常鏈接的很慢,並且鏈接上還常常斷開。的確,在這裏強調一下華爲的一部分手機確實很容易出現這種問題,有時候軟件、硬件都搞不定,並且常常性收到客戶投訴關於華爲手機鏈接穩定性問題,這個的確沒有徹底解決的辦法,只能靠App和硬件的優化,並非想甩鍋給華爲,咱也不敢問究竟是什麼緣由,並且咱們公司專門針對各個Android版本的手機作過測試,包括藍牙傳輸速率的測試,最後發現華爲P20的速度居然跟小米8的速度差了好幾倍,按理說P20手機也不便宜啊,爲何手機藍牙芯片不能作的再好一點呢?git
先肯定下列幾項是否知足:
一、藍牙是否打開
二、藍牙相關權限是否受權(6.0以上位置權限)
三、7.0以上手機不少須要手動打開GPS
複製代碼
緣由:
出現這個問題的不少是Android7.0以上手機,爲何呢?
由於Google爲了防止Android7中的BLE掃描濫用,從而作了一些限制,即不要在30s內對藍牙掃描
重複開啓-關閉超過5次。
建議:
設置掃描週期>6s, 用戶點擊掃描後不要重複進行掃描,能夠作一個是否正在掃描的標誌位,若是
正在掃描就不作重複掃描動做了。
複製代碼
BLE掃描濫用預防github
Android8.0以上退到後臺息屏後,爲了保證省電等緣由,若是不設置ScanFilters的話是默認掃不到設備的,
因此解決辦法就是設置以下:
mScannerSetting = new ScanSettings.Builder()
//退到後臺時設置掃描模式爲低功耗
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
mFilters.add(new ScanFilter.Builder()
//過濾掃描藍牙設備的主服務
.setServiceUuid(ParcelUuid.fromString("0000ffff-0000-1000-8000-00805f9bfffb"))
.build());
mScanner.startScan(mFilters, mScannerSetting, mScannerCallback);
複製代碼
息屏狀態下,藍牙掃描日誌,由於掃描週期是12s,因此打印的時間戳間隔是12s,這裏的日誌爲系統日誌。bash
翻譯:
啓動藍牙掃描。掃描結果將經過回調傳遞。對於未通過濾的掃描,掃描是中止在屏幕上關閉,以節省
電力。再次打開屏幕時,將恢復掃描。爲了不這種狀況,請使用適當的掃描過濾器進行文件掃描。
複製代碼
可能緣由:
在使用 BluetoothDevice.connectGatt() 或者 BluetoothGatt.connect() 等創建 BluetoothGatt
鏈接的時候,在任什麼時候刻都只能最多一個設備在嘗試創建鏈接。若是同時對多個藍牙設備發起創建 Gatt
鏈接請求。若是前面的設備鏈接失敗了,後面的設備請求會被永遠阻塞住,不會有任何鏈接回調。
建議:
若是要對多個設備發起鏈接請求,最好創建一個請求隊列,前一個設備請求創建鏈接,後面請求在隊列中等待
。若是鏈接成功了,就處理下一個鏈接請求。若是鏈接失敗了(例如出錯,或者鏈接超時失敗),就立刻調用
BluetoothGatt.disconnect()/close()來釋放創建鏈接請求,而後處理下一個設備鏈接請求。
複製代碼
鏈接成功後,會進行BluetoothGatt.discoverServices()去發現服務,進而設置特徵值等,由於該方法是在主
線程中執行的,因此爲了鏈接過程的可靠性,建議不要在該過程當中,在主線程中不要處理太多的操做(尤爲是頻
繁繪製操做)。
複製代碼
這個問題其實並不主要是客戶端的問題,因此不要一味的在代碼中找問題了,建議與硬件溝通,讓其進行優化
,如能夠調整設備的鏈接參數(ConnectionInterval(鏈接間隔)、SlaveLatency(從設備延遲或者從設備時
延)、SupervisionTimeout(超時時間或者監控超時)),這三個參數是低功耗藍牙中十分重要的鏈接參數,
一塊兒決定了BLE的功耗,通常硬件設備會在APP鏈接成功時主動去更新一下這三個參數,以保證不一樣手機的差別
性獲得一致,可是APP端是沒辦法控制這三個參數的。
複製代碼
標準答案是7個,爲何是7個,這個咱們能夠從以下圖所示的底層藍牙源碼中找到依據。
複製代碼
android.googlesource.com/platform/ex…app
發起藍牙Gatt鏈接 BluetoothDevice.connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback),這裏有一個參數autoConnect,若是爲 true
的話,系統就會發起一個後臺鏈接,等到系統發現了一個設備,就會自動連上,一般這個過程是很是慢的。爲
false 的話,就會直接鏈接,一般會比較快。一樣,BluetoothGatt.connect()只能發起一個後臺鏈接,不是直
接鏈接,因此鏈接時設置autoConnect參數設置爲false,若是想實現重連功能的話,本身去手動實現吧,實在不
想手動寫,那就用Android-BLE庫吧,你想要的基本都有。
複製代碼
緣由:可能因爲首次鏈接藍牙後沒有釋放掉gatt資源致使的藍牙協議棧異常,從而出現133或257
19等值不爲0:因爲協議棧,鏈接創建失敗
建議:在onConnectionStateChange()回調中判斷,若state非0(鏈接斷開),調用gatt.close(),手動釋放掉
gatt相關資源
複製代碼
緣由:
一、首先肯定主服務是否正確,再看設置的讀、寫特徵值是否正確
二、由於BLE發現服務和設置特徵、通知等是須要耗時的,因此你並不能鏈接成功後立馬發送數據,能夠等到在
onDescriptorWrite()回調時,或者手動延遲一段時間再去作發送操做。
複製代碼
BLE4.0藍牙發送數據,單次最大傳輸20個byte,若是是通常的協議命令,如:開關燈、前進左右等等,是不須要
分包的,若是是須要發送如:圖片、BIN文檔、音樂等大數據量的文件,則必須進行分包發送,BLE庫中已經提
供了發送大數據包的接口,須要的小夥伴能夠去下載DEMO查看用法。
複製代碼