當前位置:首頁 » 安卓系統 » android40ble藍牙

android40ble藍牙

發布時間: 2024-11-01 17:36:58

㈠ Android-Ble藍牙開發Demo示例–掃描,連接,發送和接收數據,分包解包(附源碼)

萬物互聯的物聯網時代的已經來臨,ble藍牙開發在其中扮演著舉重若輕的角色。最近剛好閑一點,抽時間梳理下這塊的知識點。

涉及ble藍牙通訊的客戶端(開啟、掃描、連接、發送和接收數據、分包解包)和服務端(初始化廣播數據、開始廣播、配置Services、Server回調操作)整個環節以及一些常見的問題即踩過的一些坑。

比如
1、在Android不同版本或不同手機的適配問題,掃描不到藍牙設備
2、如何避免ble藍牙連接出現133錯誤?
3、單次寫的數據大小有20位元組限制,如何發送長數據

藍牙有傳統(經典)藍牙和低功耗藍牙BLE(Bluetooth Low Energy)之分,兩者的開發的API不一樣,本文主講Ble藍牙開發,傳統藍牙不展開,有需要的可以自行了解。

相對傳統藍牙,BLE低功耗藍牙,主要特點是快速搜索,快速連接,超低功耗保持連接和數據傳輸。

客戶端

服務端

Android4.3(API Level 18)開始引入BLE的核心功能並提供了相應的 API。應用程序通過這些 API 掃描藍牙設備、查詢 services、讀寫設備的 characteristics(屬性特徵)等操作。

BLE藍牙協議是GATT協議, BLE相關類不多, 全都位於android.bluetooth包和android.bluetooth.le包的幾個類:
android.bluetooth.
.BluetoothGattService 包含多個Characteristic(屬性特徵值), 含有唯一的UUID作為標識
.BluetoothGattCharacteristic 包含單個值和多個Descriptor, 含有唯一的UUID作為標識
.BluetoothGattDescriptor 對Characteristic進行描述, 含有唯一的UUID作為標識

.BluetoothGatt 客戶端相關
.BluetoothGattCallback 客戶端連接回調
.BluetoothGattServer 服務端相關
.BluetoothGattServerCallback 服務端連接回調

android.bluetooth.le.
.AdvertiseCallback 服務端的廣播回調
.AdvertiseData 服務端的廣播數據
.AdvertiseSettings 服務端的廣播設置
.BluetoothLeAdvertiser 服務端的廣播

.BluetoothLeScanner 客戶端掃描相關(Android5.0新增)
.ScanCallback 客戶端掃描回調
.ScanFilter 客戶端掃描過濾
.ScanRecord 客戶端掃描結果的廣播數據
.ScanResult 客戶端掃描結果
.ScanSettings 客戶端掃描設置

BLE設備分為兩種設備: 客戶端(也叫主機/中心設備/Central), 服務端(也叫從機/外圍設備/peripheral)
客戶端的核心類是 BluetoothGatt
服務端的核心類是 BluetoothGattServer 和 BluetoothLeAdvertiser
BLE數據的核心類是 BluetoothGattCharacteristic 和 BluetoothGattDescriptor

下面詳細講解下客戶端和服務端的開發步驟流程

安卓手機涉及藍牙許可權問題,藍牙開發需要在AndroidManifest.xml文件中添加許可權聲明:

在搜索設備之前需要詢問打開手機藍牙:

注意: BLE設備地址是動態變化(每隔一段時間都會變化),而經典藍牙設備是出廠就固定不變了!

通過掃描BLE設備,根據設備名稱區分出目標設備targetDevice,下一步實現與目標設備的連接,在連接設備之前要停止搜索藍牙;停止搜索一般需要一定的時間來完成,最好調用停止搜索函數之後加以100ms的延時,保證系統能夠完全停止搜索藍牙設備。停止搜索之後啟動連接過程;

BLE藍牙的連接方法相對簡單只需調用connectGatt方法;

參數說明

與設備建立連接之後與設備通信,整個通信過程都是在BluetoothGattCallback的非同步回調函數中完成;

BluetoothGattCallback中主要回調函數如下:

上述幾個回調函數是BLE開發中不可缺少的;

當調用targetdDevice.connectGatt(context, false, gattCallback)後系統會主動發起與BLE藍牙設備的連接,若成功連接到設備將回調onConnectionStateChange方法,其處理過程如下:

判斷newState == BluetoothGatt.STATE_CONNECTED表明此時已經成功連接到設備;

mBluetoothGatt.discoverServices();

掃描BLE設備服務是安卓系統中關於BLE藍牙開發的重要一步,一般在設備連接成功後調用,掃描到設備服務後回調onServicesDiscovered()函數,函數原型如下:

BLE藍牙開發主要有負責通信的BluetoothGattService完成的。當且稱為通信服務。通信服務通過硬體工程師提供的UUID獲取。獲取方式如下:

具體操作方式如下:

開啟監聽,即建立與設備的通信的首發數據通道,BLE開發中只有當客戶端成功開啟監聽後才能與服務端收發數據。開啟監聽的方式如下:

BLE單次寫的數據量大小是有限制的, 通常是20位元組 ,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20位元組,分兩種包,數據包和非數據包。對於數據包,頭兩個位元組表示包的序號,剩下的都填充數據。對於非數據包,主要是發送一些控制信息。
監聽成功後通過向 writeCharacteristic寫入數據實現與服務端的通信。寫入方式如下:

其中:value一般為Hex格式指令,其內容由設備通信的藍牙通信協議規定;

若寫入指令成功則回調BluetoothGattCallback中的onCharacteristicWrite()方法,說明將數據已經發送給下位機;

若發送的數據符合通信協議,則服務端會向客戶端回復相應的數據。發送的數據通過回調onCharacteristicChanged()方法獲取,其處理方式如下:

通過向服務端發送指令獲取服務端的回復數據,即可完成與設備的通信過程;

當與設備完成通信之後之後一定要斷開與設備的連接。調用以下方法斷開與設備的連接:

源碼上傳在CSDN上了,有需要的可以借鑒。

=====> Android藍牙Ble通訊Demo示例源碼–掃描,連接,發送和接收數據,分包解包

BLE單次寫的數據量大小是有限制的,通常是20位元組,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20位元組,分兩種包,數據包和非數據包。對於數據包,頭兩個位元組表示包的序號,剩下的都填充數據。對於非數據包,主要是發送一些控制信息。
總體流程如下:
1、定義通訊協議,如下(這里只是個舉例,可以根據項目需求擴展)

2、封裝通用發送數據介面(拆包)
該介面根據會發送數據內容按最大位元組數拆分(一般20位元組)放入隊列,拆分完後,依次從隊列里取出發送

3、封裝通用接收數據介面(組包)
該介面根據從接收的數據按協議里的定義解析數據長度判讀是否完整包,不是的話把每條消息累加起來

4、解析完整的數據包,進行業務邏輯處理

5、協議還可以引入加密解密,需要注意的選演算法參數的時候,加密後的長度最好跟原數據長度一致,這樣不會影響拆包組包

一般都是Android版本適配以及不同ROM機型(小米/紅米、華為/榮耀等)(EMUI、MIUI、ColorOS等)的許可權問題

藍牙開發中有很多問題,要靜下心分析問題,肯定可以解決的,一起加油;

㈡ Android BLE藍牙踩坑總結

自從 Android-BLE 庫開源了一段時間以來,越來越多的小夥伴問到了各種各樣的關於BLE的奇怪問題,在這里我想跟大家分享一下本人對於Android BLE藍牙的一些看法和解決方式,避免剛接觸的小夥伴再次踩坑。

很多人曾問過我這個問題,為什麼其他手機都沒什麼問題,就華為的一些手機老是連接不穩定,經常連接的很慢,而且連接上還經常斷開。的確,在這里強調一下華為的一部分手機確實很容易出現這種問題,有時候軟體、硬體都搞不定,而且經常性收到客戶投訴關於華為手機連接穩定性問題,這個的確沒有完全解決的辦法,只能靠App和硬體的優化,並不是想甩鍋給華為,咱也不敢問到底是什麼原因,而且我們公司專門針對各個Android版本的手機做過測試,包括藍牙傳輸速率的測試,最後發現華為P20的速度竟然跟小米8的速度差了好幾倍,按理說P20手機也不便宜啊,為什麼手機藍牙晶元不能做的再好一點呢?

BLE掃描濫用預防

AOSP-BLE掃描濫用說明

息屏狀態下,藍牙掃描日誌,因為掃描周期是12s,所以列印的時間戳間隔是12s,這里的日誌為系統日誌。

https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/include/bt_target.h#1428

stackoverflow問答社區

㈢ Android BLE藍牙連接異常處理

藍牙通信過程中異常很常見,大致有以下幾種:

1,連接

2,發現服務

3,讀寫

4,通知

連接失敗可能是設備端原因,也可能是手機端原因。不同的手機來自不同的廠家,用的不同的晶元和藍牙協議棧都會導致藍牙功能的表現不一致,這都會導致各式各樣的兼容性問題,可能有的手機連接成功率高,有的成功率低。設備端原因可能有些時候出現異常導致死機無響應,或某些參數設置得有問題。但對於Android應用層開發來說,能做的很有限,藍牙通信是在系統服務進程中處理的,我們無法跨進程改變系統的行為,如果是在一個進程我們還可能通過Hook等手段來調整其內在邏輯。另外應用層的介面只是將請求封裝傳遞給系統服務進程,並未做一些實質性的通信,所以應用層雖然是同一個進程的,但是Hook意義也不大。所以我們能做的僅僅是看怎樣調整介面的調用,使得整體穩定性更好一點而已。

連接失敗分兩種,一種是超時,一種是提前返回失敗。

關於超時,一般是設備不在周圍,或設備斷電未發廣播,或設備當前被其他人連接。系統默認超時為30s,通常返回133,我們也可以自己設置更短的超時時間,超時則closeGatt,然後重新連接。

關於提前返回失敗,一般是有明確的異常,可能是手機藍牙的異常或者設備異常。

這兩種情況建議closeGatt,延時500ms,然後重試。如果重試三次仍然失敗,則可以考慮提示用戶重啟手機藍牙,或者檢查設備是否正常工作。

還有一種情況,連接成功後沒過多久連接又斷開了,這有可能是設備主動斷開,連接成功後有的設備會等待鑒權,如果一定時間內手機端還未發起鑒權則設備端主動斷開。也可能連接信道不夠穩定導致斷開的,此時closeGatt並重新連接即可。

當連接斷開時,會收到onConnectionStateChanged回調,這個回調可能會有一定延時,甚至有5s以上。解決的辦法是輪詢,如每隔1s發起一次讀請求,如果連接斷了會立即返回失敗。

如果藍牙連接不穩定,可以考慮關掉WIFI,因為WIFI通常和藍牙共用一個天線。

有的手機上discoverService可能會回調不止一次onServiceDiscover,這個要注意防禦。

當連接建立後,可以由設備端發起更改連接間隔,這樣能加快後續發現服務以及數據讀寫的速度。有的手機discover service很慢,原因是connect interval太大了,有的手機會主動向設備發起更改connect interval,而有的手機卻不會。這樣的話connect interval相差就會很大,實踐中發現有的手機是7ms,有的手機是默認的50ms,所以發現service都要8s,甚至20s的都很尋常,這對用戶來說是無法忍受的。所以比較好的辦法是設備主動發起更改connect interval,而Android系統是沒有提供對應API的。

如果發現服務失敗,通常來說不用closeGatt,重試一下就好了。如果重試三次還失敗,建議清一下緩存,再closeGatt,重新連接。

讀寫失敗要看失敗的原因是什麼,如果是許可權問題,則需要和設備端確認是否開放了相應的讀寫許可權。也可能是要讀寫的character不存在,可能是設備端修改了固件,手機端需要刷新一下藍牙緩存,closeGatt再重新連接。如果是其它未知錯誤,則重試三次,仍然失敗則closeGatt。不過通常來說如果是因為連接出了問題導致讀寫失敗的,會收到onConnectionStateChanged回調,此時就不用再無謂的重試了,直接closeGatt,重新連接。

打開/關閉character的notify,必須等收到onDescriptorWrite回調之後才算結束,才能開始下一個任務。

如果打開notify失敗,則可以改成周期性輪詢的方式去查詢character的值。

可參考該文章

Android-BLE-Issues

熱點內容
查看加密空間說說 發布:2024-11-23 12:37:47 瀏覽:1
安卓手機在哪裡退款 發布:2024-11-23 12:36:53 瀏覽:964
ftp多少w 發布:2024-11-23 12:33:21 瀏覽:309
linuxsvn重啟服務 發布:2024-11-23 12:31:24 瀏覽:557
西軟伺服器地址 發布:2024-11-23 12:27:20 瀏覽:7
二進制java 發布:2024-11-23 12:25:01 瀏覽:498
和包在京東支付密碼是什麼 發布:2024-11-23 12:24:52 瀏覽:48
風光腳本 發布:2024-11-23 12:24:09 瀏覽:118
編譯局年鑒怎麼寫 發布:2024-11-23 12:23:59 瀏覽:977
linux解壓tar命令 發布:2024-11-23 12:21:02 瀏覽:656