一、藍牙簡介
① 概念
- 藍牙是短距離無線通信的一種方式,支持藍牙的兩個設備必須配對后才能通信。HarmonyOS 藍牙主要分為傳統(tǒng)藍牙和低功耗藍牙(通常稱為 BLE,Bluetooth Low Energy)。
- 傳統(tǒng)藍牙指的是藍牙版本 3.0 以下的藍牙,低功耗藍牙指的是藍牙版本 4.0 以上的藍牙。
- 當前藍牙的配對方式有兩種:藍牙協(xié)議 2.0 以下支持 PIN 碼(Personal Identification Number,個人識別碼)配對,藍牙協(xié)議 2.1 以上支持簡單配對。
② 傳統(tǒng)藍牙
- 傳統(tǒng)藍牙本機管理:打開和關閉藍牙、設置和獲取本機藍牙名稱、掃描和取消掃描周邊藍牙設備、獲取本機藍牙 profile 對其他設備的連接狀態(tài)、獲取本機藍牙已配對的藍牙設備列表。
- 傳統(tǒng)藍牙遠端設備操作:查詢遠端藍牙設備名稱和 MAC 地址、設備類型和配對狀態(tài),以及向遠端藍牙設備發(fā)起配對。
③ BLE
- BLE 設備交互時會分為不同的角色:
-
- 中心設備和外圍設備:中心設備負責掃描外圍設備、發(fā)現(xiàn)廣播。外圍設備負責發(fā)送廣播。
-
- GATT(Generic Attribute Profile,通用屬性配置文件)服務端與 GATT 客戶端:兩臺設備建立連接后,其中一臺作為 GATT 服務端,另一臺作為 GATT 客戶端。
- HarmonyOS 低功耗藍牙提供的功能有:
-
- BLE 掃描和廣播:根據(jù)指定狀態(tài)獲取外圍設備、啟動或停止 BLE 掃描、廣播。
-
- BLE 中心設備與外圍設備進行數(shù)據(jù)交互:BLE 外圍設備和中心設備建立 GATT 連接后,中心設備可以查詢外圍設備支持的各種數(shù)據(jù),向外圍設備發(fā)起數(shù)據(jù)請求,并向其寫入特征值數(shù)據(jù)。
-
- BLE 外圍設備數(shù)據(jù)管理:BLE 外圍設備作為服務端,可以接收來自中心設備(客戶端)的 GATT 連接請求,應答來自中心設備的特征值內容讀取和寫入請求,并向中心設備提供數(shù)據(jù)。同時外圍設備還可以主動向中心設備發(fā)送數(shù)據(jù)。
④ 權限申請
- 調用藍牙的打開接口需要 ohos.permission.USE_BLUETOOTH 權限。
- 調用藍牙掃描接口需要 ohos.permission.LOCATION 權限和 ohos.permission.DISCOVER_BLUETOOTH 權限。
二、傳統(tǒng)藍牙本機管理
① 應用場景
- 傳統(tǒng)藍牙本機管理主要是針對藍牙本機的基本操作,包括打開和關閉藍牙、設置和獲取本機藍牙名稱、掃描和取消掃描周邊藍牙設備、獲取本機藍牙profile對其他設備的連接狀態(tài)、獲取本機藍牙已配對的藍牙設備列表。
② API 說明
- 藍牙本機管理類 BluetoothHost 的主要接口:
接口名功能描述
| getDefaultHost?(Context context) | 獲取BluetoothHost實例,去管理本機藍牙操作 |
| enableBt?() | 打開本機藍牙 |
| disableBt?() | 關閉本機藍牙 |
| setLocalName?(String name) | 設置本機藍牙名稱 |
| getLocalName?() | 獲取本機藍牙名稱 |
| getBtState?() | 獲取本機藍牙狀態(tài) |
| startBtDiscovery?() | 發(fā)起藍牙設備掃描 |
| cancelBtDiscovery?() | 取消藍牙設備掃描 |
| isBtDiscovering?() | 檢查藍牙是否在掃描設備中 |
| getProfileConnState?(int profile) | 獲取本機藍牙profile對其他設備的連接狀態(tài) |
| getPairedDevices?() | 獲取本機藍牙已配對的藍牙設備列 |
③ 打開藍牙
- 調用 BluetoothHost 的 getDefaultHost?(Context context) 接口,獲取 BluetoothHost 實例,管理本機藍牙操作。
- 調用 enableBt?() 接口,打開藍牙。
- 調用 getBtState?(),查詢藍牙是否打開。
// 獲取藍牙本機管理對象BluetoothHost bluetoothHost = BluetoothHost.getDefaultHost(context);// 調用打開接口bluetoothHost.enableBt();// 調用獲取藍牙開關狀態(tài)接口int state = bluetoothHost.getBtState();
④ 藍牙掃描
- 開始藍牙掃描前要先注冊廣播 BluetoothRemoteDevice.EVENT_DEVICE_DISCOVERED。
- 調用 startBtDiscovery() 接口開始進行掃描外圍設備。
- 如果想要獲取掃描到的設備,必須在注冊廣播時繼承實現(xiàn) CommonEventSubscriber 類的 onReceiveEvent(CommonEventData data) 方法,并接收 EVENT_DEVICE_DISCOVERED 廣播。
// 開始掃描bluetoothHost.startBtDiscovery();// 接收系統(tǒng)廣播public class MyCommonEventSubscriber extends CommonEventSubscriber {@Overridepublic void onReceiveEvent(CommonEventData data) {if (data == null) {return;}Intent info = data.getIntent();if (info == null) {return;}// 獲取系統(tǒng)廣播的actionString action = info.getAction();// 判斷是否為掃描到設備的廣播if (BluetoothRemoteDevice.EVENT_DEVICE_DISCOVERED.equals(action)) { IntentParams myParam = info.getParams(); BluetoothRemoteDevice device = (BluetoothRemoteDevice) myParam.getParam(BluetoothRemoteDevice.REMOTE_DEVICE_PARAM_DEVICE);}}}
三、傳統(tǒng)藍牙遠端設備操作
① 應用場景
- 傳統(tǒng)藍牙遠端管理操作主要是針對遠端藍牙設備的基本操作,包括獲取遠端藍牙設備地址、類型、名稱和配對狀態(tài),以及向遠端設備發(fā)起配對。
② API 說明
- 藍牙遠端設備管理類 BluetoothRemoteDevice 的主要接口:
接口名功能描述
| getDeviceAddr?() | 獲取遠端藍牙設備地址 |
| getDeviceClass?() | 獲取遠端藍牙設備類型 |
| getDeviceName?() | 獲取遠端藍牙設備名稱 |
| getPairState?() | 獲取遠端設備配對狀態(tài) |
| startPair?() | 向遠端設備發(fā)起配對 |
③ 開發(fā)流程
- 調用 BluetoothHost 的 getDefaultHost?(Context context) 接口,獲取 BluetoothHost 實例,管理本機藍牙操作。
- 調用 enable?Bt() 接口,打開藍牙。
- 調用 startBtDiscovery?(),掃描設備。
- 調用 startPair(),發(fā)起配對。
// 獲取藍牙本機管理對象BluetoothHost bluetoothHost = BluetoothHost.getDefaultHost(context);// 調用打開接口bluetoothHost.enableBt();// 調用掃描接口bluetoothHost.startBtDiscovery(); //設置界面會顯示出掃描結果列表,點擊藍牙設備去配對BluetoothRemoteDevice device = bluetoothHost.getRemoteDev(TEST_ADDRESS);device.startPair();
四、BLE 掃描和廣播
① 應用場景
- 通過 BLE 掃描和廣播提供的開放能力,可以根據(jù)指定狀態(tài)獲取外圍設備、啟動或停止 BLE 掃描、廣播。
② API 說明
- BLE 中心設備管理類 BleCentralManager 的主要接口:
接口名功能描述
| startScan(List filters) | 進行BLE藍牙掃描,并使用filters對結果進行過濾 |
| stopScan() | 停止BLE藍牙掃描 |
| getDevicesByStates(int[] states) | 根據(jù)狀態(tài)獲取連接的外圍設備 |
| BleCentralManager(Context context, BleCentralManagerCallback callback) | 獲取中心設備管理對象 |
- 中心設備管理回調類 BleCentralManagerCallback 的主要接口:
接口名功能描述
| scanResultEvent?(BleScanResult result) | 掃描到BLE設備的結果回調 |
| groupScanResultsEvent?(List scanResults) | 掃描到一組BLE設備的結果回調 |
| scanFailedEvent?(int resultCode) | 啟動掃描失敗的回調 |
- BLE 廣播相關的 BleAdvertiser 類和 BleAdvertiseCallback 類的主要接口:
接口名功能描述
| BleAdvertiser(Context context, BleAdvertiseCallback callback) | 用于獲取廣播操作對象 |
| startAdvertising(BleAdvertiseSettings settings, BleAdvertiseData advData, BleAdvertiseData scanResponse) | 進行BLE廣播,第一個參數(shù)為廣播參數(shù),第二個為廣播數(shù)據(jù),第三個參數(shù)是掃描和廣播數(shù)據(jù)參數(shù)的響應 |
| stopAdvertising() | 停止BLE廣播 |
| startResultEvent(int result) | 廣播回調結果 |
③ 中心設備進行 BLE 掃描
- 進行 BLE 掃描之前先要繼承 BleCentralManagerCallback 類實現(xiàn) scanResultEvent 和 scanFailedEvent 回調函數(shù),用于接收掃描結果。
- 調用 BleCentralManager(BleCentralManagerCallback callback) 接口獲取中心設備管理對象。
- 獲取掃描過濾器,過濾器為空時為不使用過濾器掃描,然后調用 startScan() 開始掃描 BLE 設備,在回調中獲取掃描到的 BLE 設備。
// 實現(xiàn)掃描回調public class ScanCallback implements BleCentralManagerCallback {List
<BleScanResult> results = new ArrayList
<BleScanResult>();@Overridepublic void scanResultEvent(BleScanResult resultCode) {// 對掃描結果進行處理results.add(resultCode);}@Override public void scanFailedEvent(int resultCode) { HiLog.warn(TAG,"Start Scan failed, Code: %{public}d", resultCode); }@Overridepublic void groupScanResultsEvent?(final List
<BleScanResult> scanResults){// 對掃描結果進行處理}}// 獲取中心設備管理對象private ScanCallback centralManagerCallback = new ScanCallback();private BleCentralManager centralManager = new BleCentralManager(context, centralManagerCallback);// 創(chuàng)建掃描過濾器然后開始掃描List
<BleScanFilter> filters = new ArrayList
<BleScanFilter>();centralManager.startScan(filters);
④ 外圍設備進行 BLE 廣播
- 進行 BLE 廣播前需要先繼承 advertiseCallback 類實現(xiàn) startResultEvent 回調,用于獲取廣播結果。
- 調用接口 BleAdvertiser(Context context, BleAdvertiseCallback callback) 獲取廣播對象,構造廣播參數(shù)和廣播數(shù)據(jù)。
- 調用 startAdvertising(BleAdvertiseSettings settings, BleAdvertiseData advData, BleAdvertiseData scanResponse) 接口開始 BLE 廣播。
// 實現(xiàn)BLE廣播回調private BleAdvertiseCallback advertiseCallback = new BleAdvertiseCallback() {@Override public void startResultEvent(int result) {if(result == BleAdvertiseCallback.RESULT_SUCC){// 開始BLE廣播成功}else {// 開始BLE廣播失敗}}};// 獲取BLE廣播對象private BleAdvertiser advertiser = new BleAdvertiser(this,advertiseCallback);// 創(chuàng)建BLE廣播參數(shù)和數(shù)據(jù)private BleAdvertiseData data = new BleAdvertiseData.Builder() .addServiceUuid(SequenceUuid.uuidFromString(Server_UUID)) // 添加服務的UUID .addServiceData(SequenceUuid.uuidFromString(Server_UUID), new byte[]{0x11}) // 添加廣播數(shù)據(jù)內容.build();private BleAdvertiseSettings advertiseSettings = new BleAdvertiseSettings.Builder() .setConnectable(true) // 設置是否可連接廣播.setInterval(BleAdvertiseSettings.INTERVAL_SLOT_DEFAULT) // 設置廣播間隔.setTxPower(BleAdvertiseSettings.TX_POWER_DEFAULT) // 設置廣播功率.build();// 開始廣播advertiser.startAdvertising(advertiseSettings, data, null);
五、BLE 中心設備與外圍設備進行數(shù)據(jù)交互
① 應用場景
- BLE 外圍設備和中心設備建立 GATT 連接,通過該連接中心設備可以獲取外圍設備支持的 Service、Characteristic?、Descriptor、RSSI 等數(shù)據(jù)。同時,中心設備可以向外圍設備進行數(shù)據(jù)請求,并向外圍設備寫入 Characteristic、Descriptor 等特征值數(shù)據(jù)。
② API 說明
- 低功耗藍牙外圍設備操作類 BlePeripheralDevice 的接口說明如下:
接口名功能描述
| connect(boolean isAutoConnect, BlePeripheraCallback callback) | 重新連接GATT外圍設備,isAutoConnect表示是否自動進行連接 |
| discoverServices() | 搜索外圍設備支持的服務,特征和描述 |
| getServices() | 獲取外圍設備支持的所有GATT服務 |
| getService(UUID uuid) | 根據(jù)UUID獲取外圍設備支持的某個GATT服務 |
| disconnect() | 與外圍設備斷開BLE連接 |
| close() | 關閉藍牙GATT客戶端 |
| readCharacteristic(GattCharacteristic characteristic) | 讀取外圍設備GATT特征 |
| writeCharacteristic(GattCharacteristic characteristic) | 寫指定外圍設備的GATT特征值 |
| setNotifyCharacteristic(GattCharacteristic characteristic, boolean enable) | 設置指定GATT特征通知的使能/去使能 |
| readDescriptor (GattDescriptor descriptor) | 讀取外圍設備GATT描述值 |
| writeDescriptor(GattDescriptor descriptor) | 寫指定外圍設備的GATT描述值 |
| readRemoteRssiValue() | 讀取已連接外圍設備的RSSI |
| requestBleConnectionPriority(int connPriority) | 請求鏈接參數(shù)更新 |
| requestBleMtuSize(int mtu) | 請求用于給定連接的MTU大小 |
- 低功耗藍牙外圍設備操作回調類 BlePeripheralCallback 的接口說明如下:
接口名功能描述
| servicesDiscoveredEvent(int status) | 外圍設備服務發(fā)生更新觸發(fā)的回調 |
| connectionStateChangedEvent(int connectionState) | 外圍設備GATT連接狀態(tài)發(fā)生變化時的回調 |
| characteristicReadEvent(GattCharacteristic characteristic, int ret) | GATT特征值讀操作回調 |
| characteristicWriteEvent(GattCharacteristic characteristic, int ret) | GATT特征值寫操作回調 |
| characteristicChangedEvent(GattCharacteristic characteristic) | 外圍設備特征通知觸發(fā)的回調 |
| descriptorReadEvent(GattDescriptor descriptor, int ret) | GATT描述值讀操作回調 |
| descriptorWriteEvent(GattDescriptor descriptor, int ret) | GATT描述值寫操作回調 |
| readRemoteRssiEvent(int rssi, int ret) | 外圍設備發(fā)來讀取RSSI的回調 |
| mtuUpdateEvent(int mtu, int ret) | GATT設備鏈接的MTU變化通知的回調 |
③ 開發(fā)流程
- 調用 startScan() 接口啟動 BLE 掃描來獲取外圍設備。
- 獲取到外圍設備后,調用 connect(boolean isAutoConnect, BlePeripheraCallback callback) 建立與外圍 BLE 設備的 GATT 連接,boolean 參數(shù) isAutoConnect 用于設置是否允許設備在可發(fā)現(xiàn)距離內自動建立 GATT 連接。
- 啟動 GATT 連接后,會觸發(fā) connectionStateChangedEvent(int connectionState) 回調,根據(jù)回調結果判斷是否連接 GATT 成功。
- 在 GATT 連接成功時,中心設備可以調用 discoverServices() 接口,獲取外圍設備支持的 Services、Characteristics 等特征值,在回調 servicesDiscoveredEvent(int status) 中獲取外圍設備支持的服務和特征值,并根據(jù) UUID 判斷是什么服務。
- 根據(jù)獲取到的服務和特征值,調用 read 和 write 方法可以讀取或者寫入對應特征值數(shù)據(jù)。
private List
<GattService> services;// 創(chuàng)建掃描過濾器然后開始掃描List
<BleScanFilter> filters = new ArrayList
<BleScanFilter>();centralManager.startScan(filters);// 與外圍設備建立連接,允許自動回連,連接會觸發(fā)connectionStateChangedEvent回調MyBlePeripheralCallback callback = new MyBlePeripheralCallback();peripheraDevice.connect(true, callback);// 連接后讀取外圍設備RSSI值,獲取后觸發(fā)readRemoteRssiEvent()回調peripheraDevice.readRemoteRssiValue();// 實現(xiàn)外圍設備操作回調private class MyBlePeripheralCallback extends BlePeripheralCallback {@Overridepublic void connectionStateChangedEvent(int connectionState) { // GATT連接狀態(tài)變化回調if (connectionState == ProfileBase.STATE_CONNECTED){peripheraDevice.discoverServices(); // 連接成功獲取外圍設備的Service} }@Overridepublic void servicesDiscoveredEvent(int status) { // 獲取外圍設備Service的回調if (status == BlePeripheralDevice.OPERATION_SUCC){services = peripheraDevice.getServices(); // 獲取Service成功后獲服務列表for (GattService service : services){// 對每個服務進行相應操作}}}@Overridepublic void characteristicChangedEvent(GattCharacteristic charecteristic) { // 外圍設備主動向中心設備發(fā)送特征值通知時觸發(fā)回調// 根據(jù)通知的charecteristic獲取特征值攜帶的數(shù)據(jù)}@Overridepublic void characteristicWriteEvent(GattCharacteristic charecteristic, int ret) {if (ret == BlePeripheralDevice.OPERATION_SUCC){// 向外圍設備寫特征值數(shù)據(jù)成功后的操作}}@Overridepublic void characteristicReadEvent(GattCharacteristic charecteristic, int ret) {if (ret == BlePeripheralDevice.OPERATION_SUCC){// 向外圍設備寫特征值數(shù)據(jù)成功后的操作}}@Overridepublic void descriptorReadEvent(GattDescriptor descriptor, int ret) {// 向外圍設備讀描述值數(shù)據(jù)成功后的操作}@Overridepublic void descriptorWriteEvent(GattDescriptor descriptor, int ret) {// 向外圍設備寫描述值數(shù)據(jù)成功后的操作}@Overridepublic void readRemoteRssiEvent(int rssi, int ret) { if (ret == BlePeripheralDevice.OPERATION_SUCC){// 讀取外圍設備RSSI值成功后的操作,對端RSSI值為rssi}}}
六、BLE 外圍設備數(shù)據(jù)管理
① 應用場景
- BLE 外圍設備作為服務端,可以接收來自中心設備(客戶端)的 GATT 連接請求,應答來自中心設備的特征值內容讀取和寫入請求,并向中心設備提供數(shù)據(jù),從而實現(xiàn)信息交互和消息同步。同時外圍設備還可以主動向中心設備發(fā)送數(shù)據(jù)。
② API 說明
- 低功耗藍牙外圍設備操作類 BlePeripheralManager 的接口說明如下:
接口名功能描述
| BlePeripheralManager(Context context, BlePeripheralManagerCallback callback, int transport) | 獲取外圍設備管理回調對象 |
| getServices() | 獲取外圍設備的所有服務 |
| addService(GattService service) | 將GATT服務加入服務端 |
| cancelConnection(BlePeripheralDevice device) | 取消與中心設備的GATT連接 |
| clearServices() | 刪除所有的GATT服務 |
| close() | 關閉GATT服務端 |
| getDevicesByStates(int[] states) | 通過狀態(tài)獲取連接的中心設備列表 |
| notifyCharacteristicChanged(BlePeripheralDevice device, GattCharacteristic characteristic, boolean confirm) | 通知中心設備特征值出現(xiàn)變化 |
| removeGattService(GattService service) | 移除特定的服務 |
| sendResponse(BlePeripheralDevice device, int requestId, int status, int offset, byte[] value) | 發(fā)送回復給中心設備 |
- 低功耗藍牙外圍設備管理回調類 BlePeripheralManagerCallback 的接口說明如下:
接口名功能描述
| receiveCharacteristicReadEvent(BlePeripheralDevice device, int requestId, int offset, GattCharacteristic characteristic) | 收到中心設備對特征值的讀取請求回調 |
| receiveCharacteristicWriteEvent(BlePeripheralDevice device, int requestId, GattCharacteristic characteristic, boolean isPrep, boolean needRsp, int offset, byte[] value) | 收到中心設備對特征值的寫入請求 |
| connectionStateChangeEvent(BlePeripheralDevice device, int interval, int latency, int timeout, int status) | 中心設備連接事件回調 |
| receiveDescriptorReadEvent(BlePeripheralDevice device, int transId, int offset, GattDescriptor descriptor) | 收到中心設備對描述值的讀取請求回調 |
| receiveDescriptorWriteRequestEvent(BlePeripheralDevice device, int transId, GattDescriptor descriptor, boolean isPrep, boolean needRsp, int offset, byte[] value) | 收到中心設備對描述值的寫入請求回調 |
| executeWriteEvent(BlePeripheralDevice device, int requestId, boolean execute) | 向中心設備執(zhí)行寫入操作的回調 |
| mtuUpdateEvent(BlePeripheralDevice device, int mtu) | 中心設備MTU值變化的回調 |
| notificationSentEvent(BlePeripheralDevice device, int status) | 向中心設備發(fā)送通知的回調 |
| serviceAddedEvent(int status, GattService service) | 向外圍設備添加服務結果回調 |
③ 開發(fā)流程
- 調用 BlePeripheralManager(Context context, BlePeripheralManagerCallback callback, int transport) 接口創(chuàng)建外圍設備服務端并開啟服務。
- 調用 GattService(UUID uuid, boolean isPrimary) 接口創(chuàng)建服務對象,向外圍設備添加服務。
- 從回調接口 onCharacteristicWriteRequest 中獲取中心設備發(fā)送來的消息,調用 notifyCharacteristicChanged 接口向中心設備發(fā)送通知。
private BlePeripheralDevice blePeripheralDevice;private MyBlePeripheralManagerCallback peripheralManagerCallback = new MyBlePeripheralManagerCallback();// 創(chuàng)建外圍設備服務端并開啟服務private BlePeripheralManager peripheralManager = new BlePeripheralManager(this, peripheralManagerCallback, 0);// 創(chuàng)建服務對象,向外圍設備添加服務private GattService service = new GattService(UUID.fromString(Service_UUID), true);private GattCharacteristic writeCharacteristic = new GattCharacteristic(Character_UUID, GattCharacteristic.PROPERTY_WRITE, GattCharacteristic.PROPERTY_WRITE);service.addCharacteristic(writeCharacteristic);peripheralManager.addServerService(service);// 向中心設備發(fā)送通知writeCharacteristic.setValue(data);peripheralManager.notifyCharacteristicChanged(blePeripheralDevice, writeCharacteristic, false);// 外圍設備管理回調public class MyBlePeripheralManagerCallback extends BlePeripheralManagerCallback {// 中心設備向外圍設備寫入數(shù)據(jù)回調@Overridepublic void receiveCharacteristicWriteEvent(BlePeripheralDevice device, int requestId, GattCharacteristic characteristic, boolean isPrep, boolean needRsp, int offset, byte[] value){ // 中心設備寫入外圍設備的數(shù)據(jù)為value,對數(shù)據(jù)進行處理}// 外圍設備連接狀態(tài)變化回調@Overridepublic void connectionStateChangeEvent(BlePeripheralDevice device, int interval, int latency, int timeout, int status){if (status == ProfileBase.STATE_CONNECTED) {// 中心設備連接服務端成功blePeripheralDevice = device;}}// 向中心設備發(fā)送通知回調@Overridepublic void notificationSentEvent(BlePeripheralDevice device, int status){if (status == BlePeripheralDevice.OPERATION_SUCC) {// 向對中心設備發(fā)送通知成功回調}}}
總結
以上是生活随笔為你收集整理的HarmonyOS之深入解析蓝牙Bluetooth的功能和使用的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。