搞了一段時(shí)間的藍(lán)牙,現(xiàn)在閑了下來,總結(jié)一下具體的流程。沉淀一下
接下來的流程中會(huì)涉及到一下幾個(gè)類,現(xiàn)在提前說明一下作用
BluetoothManager 藍(lán)牙管理類,用于獲取藍(lán)牙適配器,藍(lán)牙連接狀態(tài)
BluetoothAdapter 掃描,獲取藍(lán)牙設(shè)備的類
BluetoothGatt 管理遠(yuǎn)程藍(lán)牙設(shè)備內(nèi)部的service,特征值
BluetoothDevice 藍(lán)牙設(shè)備的封裝類,用于獲取address,連接等作用
BluetoothAdapter.LeScanCallback 掃描設(shè)備的回調(diào)
BluetoothGattCallback 回調(diào),藍(lán)牙設(shè)備各種數(shù)據(jù)和狀態(tài)回調(diào)
BluetoothGattService 跑在遠(yuǎn)程藍(lán)牙設(shè)備中的服務(wù)
BluetoothGattCharacteristic 特征值 用于標(biāo)識(shí)可讀,,可寫,可發(fā)通知等屬性
BluetoothGattDescriptor 藍(lán)牙協(xié)議中的Descriptor
-
:獲取設(shè)備,,
-
獲取BluetoothAdapter
- 兩種方式:BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
- BluetoothAdapter.getDefaultAdapter();
使用BluetoothAdapter掃描設(shè)備,這里需要傳入LeScanCallback 用于接收掃描到的設(shè)備
public boolean startLeScan(LeScanCallback callback) { return startLeScan(null, callback); }- 在LeScanCallback中可以獲取到設(shè)備 BluetoothDevice 這個(gè)類封裝了關(guān)于遠(yuǎn)程藍(lán)牙設(shè)備的信息,有mac地址,設(shè)備名字,設(shè)備別名等信息,最重要的適用于手機(jī)和藍(lán)牙設(shè)備建立連接
-
-
連接設(shè)備
-
在這個(gè)方法中需要最重要的是傳入BluetoothGattCallback,這個(gè)回調(diào)用于接受藍(lán)牙設(shè)備的連接狀態(tài)和數(shù)據(jù),連接成功后會(huì)返回一個(gè)BluetoothGatt 獲取service Characteristic Descriptor
public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) { return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO)); } 做完以上的步驟后連接藍(lán)牙已經(jīng)完成了,剩下的是監(jiān)聽和讀寫數(shù)據(jù)了
-
監(jiān)聽數(shù)據(jù) 上面提到BluetoothGattCallback 這個(gè)回調(diào),用于接受藍(lán)牙設(shè)備的連接狀態(tài)和數(shù)據(jù),挑幾個(gè)比較常用的方法來說一下
public abstract class BluetoothGattCallback {
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
//連接狀態(tài)改變,系統(tǒng)會(huì)調(diào)用這個(gè)方法,基本套路是這樣子的,
調(diào)用mBluetoothGatt.discoverServices()
這個(gè)方法后就會(huì)回調(diào)onServicesDiscovered,如果不調(diào)用的話你就會(huì)痛苦的思考為什么
下面這個(gè)回調(diào)不走。
if (newState == BluetoothProfile.STATE_CONNECTED) {
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//用于發(fā)現(xiàn)service,BluetoothGattCharacteristic ,BluetoothGattDescriptor 這三個(gè)對象是監(jiān)聽數(shù)據(jù)的關(guān)鍵,決定你能不能讀寫數(shù)據(jù)和接收通知
1.獲取硬件商提供好的服務(wù)
BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE_UUID);
2.在服務(wù)中獲取特征值:
BluetoothGattCharacteristic TxChar = RxService.getCharacteristic(TX_CHAR_UUID);
3.在特征值中獲取描述
BluetoothGattDescriptor descriptor = TxChar.getDescriptor(CCCD);
上面的三個(gè)對象的獲取都是靠UUID來的,藍(lán)牙協(xié)議已經(jīng)定義好一些UUID,
硬件廠商也會(huì)根據(jù)需要定義自己的UUID。
UUID相當(dāng)于一個(gè)標(biāo)示符,用于獲取對象的數(shù)據(jù)或者對象,可以自行百度一下UUID
} else {
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
//當(dāng)遠(yuǎn)程藍(lán)牙設(shè)備通過特征值來發(fā)送數(shù)據(jù)給手機(jī)的時(shí)候會(huì)回調(diào),這里就是真正獲取數(shù)據(jù)的地方之一,需要注意的,
characteristic傳遞的是二進(jìn)制數(shù)據(jù),需要進(jìn)行轉(zhuǎn)換的。還有個(gè)很坑的地方,這里我覺得并非運(yùn)行在主線程的,大家可以驗(yàn)證一下
}
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
// 寫數(shù)據(jù)的回調(diào)
}
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
//當(dāng)遠(yuǎn)程藍(lán)牙設(shè)備通過特征值來發(fā)送數(shù)據(jù)給手機(jī)的時(shí)候會(huì)回調(diào),這里就是真正獲取數(shù)據(jù)的地方之一,
}
- 總結(jié):因?yàn)槟壳肮镜氖汁h(huán)只用到了讀取數(shù)據(jù)的部分,寫數(shù)據(jù)部分還沒用到。等用到了再補(bǔ)一下,而且目前也是淺顯用了一下藍(lán)牙,希望接下來有更多的機(jī)會(huì)可以用到藍(lán)牙,增加經(jīng)驗(yàn)。