谷歌官方BLEdemo詳解

** 安卓開發(fā)中或多或少會接觸到藍牙部分,像一些智能家居,藍牙手環(huán),還有一些串口數(shù)據(jù)傳輸?shù)脑O備都和藍牙相關,面試的時候有的公司也會問到一些藍牙相關的問題,這里我來說說關于低功耗藍牙的一些相關知識,這些知識也是我在網(wǎng)上查閱總結(jié)的。在百度上一搜低功耗藍牙的帖子很多,但都講的不是很全面,讓人知其然不知其所以然。這里我就從簡單的開始先分析一些谷歌的demo的代碼,看看BLE藍牙是怎么建立通信的,只要掌握了BLE藍牙通信那么再將發(fā)送接收的數(shù)據(jù)處理一下就ok了,當然光看這一篇帖子不一定會完全把低功耗藍牙弄懂,興許會遇到一些坑,但是堅持下去始終會弄懂的;**

這是網(wǎng)上提供的Android 藍牙4.0 ble 官方 demo

  • App的界面圖
app界面.jpg

App的界面很簡單就兩個界面

代碼主要包含四個類

  • DeviceScanActivity類(展示手機掃描到的BLE藍牙);

  • DeviceControlActivity類(BLE操作控制臺);

  • BluetoothLeService類(通過服務來管理藍牙,其中通過廣播來于DeviceControlActivity類通信)

  • SampleGattAttributes類(不同種類的UUID)

DeviceScanActivity類的功能:

這個類之間繼承ListActivity,顧名思義,它可能是一個展示列表,細看代碼,它切實是一個列表展示類,這個類的主要作用就是展示手機掃描到的可用藍牙;點擊選擇的BLE后將BLE的屬性(名稱和ID)傳遞到DeviceControlActivity類;

該類的主要流程就是 在onCreate方法中判斷手機是否支持BLE,然后初始化藍牙適配器,最后就是手機的權(quán)限適配(藍牙需要定位的權(quán)限)
在onResume方法中檢測藍牙是否開啟,沒有開啟那就開啟藍牙,不開啟的話那么就觸發(fā)onActivityResult方法則finish()關閉app,開啟藍牙的話則
開啟掃描 scanLeDevice(true); true為開啟掃描 false為關閉掃描;在掃描的方法scanLeDevice中可以看到通過handler計時掃描十秒鐘;
開啟掃描后將會回調(diào) mLeScanCallback 對象;在這個對象中重寫了onLeScan方法,這個方法中的參數(shù)onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)中device則為藍牙設備屬性;將藍牙設備屬性展示到列表中,通listview監(jiān)聽選中 的藍牙跳轉(zhuǎn)到DeviceControlActivity類;

DeviceControlActivity類中要功能:

開啟服務BluetoothLeService,接收服務傳過來的藍牙數(shù)據(jù);里面有幾個重要的類部類:
ServiceConnection(BinderService的返回數(shù)據(jù)接收類);BluetoothGattCallback(廣播,接收服務發(fā)送過來的消息); ExpandableListView.OnChildClickListener(這是一個list二級列表的監(jiān)聽類);里面還有一個重要的方法就displayGattServices(listview的適配器);

該類的主要流程:注冊廣播并接收,在onCreate中對一些控件的初始化,通過intent傳值獲取到藍牙的名稱和ID,然后啟動服務;在ServiceConnection內(nèi)部類中得到服務的對象 mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();在 onResume方法中通過服務的對象建立藍牙的連接,注意 藍牙連接后還并不能通信,建立通信使用通過UUID的;藍牙建立連接后會觸發(fā)廣播action為BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED方法,在這個方法中通過調(diào)用displayGattServices方法展示藍牙的UUID的數(shù)據(jù),可以看到藍牙有很多UUID,其實UUID是分可讀的,可寫的,和可讀可寫的,這應該是藍牙廠家寫好的固件;在app上我們可以挨個的點擊不同的UUID將會建立不同的連接,其中就有一種連接可以信;點擊UUID將會OnChildClickListener()方法,里面的邏輯主要就是開啟藍牙的讀取功能和開啟藍牙的的通知功能
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
mBluetoothLeService.readCharacteristic(characteristic);

BluetoothLeService類主要功能:

就是通過UUID建立藍牙通訊,readCharacteristic()開啟藍牙讀的功能,setCharacteristicNotification()開啟藍牙或禁用通知的功能;getSupportedGattServices()只有在成功完成之后才會調(diào)用此函數(shù)。在連接的設備上檢索受支持的有關協(xié)定服務列表,里面沒有藍牙寫數(shù)據(jù)的方法,要自己寫;

該類的主要流程就是通過DeviceControlActivity類傳過來的藍牙ID建立藍牙連接
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
其中里面有一個非常重要的類mGattCallback回調(diào),這里面重寫了幾個方法
onConnectionStateChange()藍牙連接狀態(tài)改變的回調(diào);
onServicesDiscovered()服務發(fā)現(xiàn)的回調(diào)在這個方法中可以建立藍牙的連接
onCharacteristicRead()藍牙的特征;
onCharacteristicChanged()Characteristic狀態(tài)改變的回調(diào)
onCharacteristicWrite)()Characteristic寫操作的結(jié)果回調(diào):

這里說一下重點:通過上面的解釋還是會知其然不知其所以然。

藍牙讀數(shù)據(jù)有兩種方法:

一種是調(diào)用readCharacteristic()方法 開啟讀 ,一種是通過通知來讀 setCharacteristicNotification方法;

通過uuid 讀某個Characteristic

開啟讀

mBluetoothLeService.readCharacteristic(characteristic);

public void readCharacteristic(BluetoothGattCharacteristiccharacteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
}

如果成功,數(shù)據(jù)會在下面的方法回調(diào)中傳進來

public void  onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

還可以通過通知的回調(diào)方法讀取數(shù)據(jù) 這種方式不用手機去輪詢地讀設備上的數(shù)據(jù)。

 //設置true為啟用通知,false反之
  setCharacteristicNotification(mNotifyCharacteristic, true);

有消息來后會回調(diào)方法
public void  onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

寫數(shù)據(jù)就更簡單了
通過UUID獲取到BluetoothGattCharacteristic

BluetoothGattCharacteristic alertLevel =linkLossService.getCharacteristic(UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3"));
alertLevel.setValue(values_on);
status = mBluetoothGatt.writeCharacteristic(alertLevel);

status如果為true,表示寫操作已經(jīng)成功執(zhí)行,BluetoothGattCallback抽象類的一個方法會被執(zhí)行,如果剛好你又重寫了這個方法,就可以打印一些消息了

public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristiccharacteristic, int status){

}

官方的demo沒有用發(fā)送數(shù)據(jù)的代碼,接收數(shù)據(jù)也是16進制,這個需要自己按實際情況修改代碼或是在網(wǎng)上找一些demo有收發(fā)功能的,開放項目復雜多變,這里很難以偏概全,就不一一展示了;

總結(jié):藍牙收發(fā)數(shù)據(jù)每次最多20個字節(jié),這就要對接收的數(shù)據(jù)進行拼接,截取了;發(fā)送數(shù)據(jù)也是以20個字節(jié)為單位,一段一段發(fā)送;藍牙對于有些人來說也許會很難, 但是琢磨久了就會看懂的;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容