關(guān)于藍(lán)牙ble開發(fā)相關(guān)知識(shí)

藍(lán)牙的基礎(chǔ)知識(shí)

1. 相關(guān)權(quán)限申請(qǐng)

權(quán)限

android:name="android.permission.BLUETOOTH"/>

android:name="android.permission.BLUETOOTH_ADMIN"/>

注意:android6.0后?需要再添加如下權(quán)限定位權(quán)限 (如下一個(gè)就可以了 也可以多個(gè)申請(qǐng))

android:name="android.permission.ACCESS_COARSE_LOCATION"/>

android:name="android.permission.ACCESS_FINE_LOCATION"/>

2. 搜索藍(lán)牙流程

2.1 打開藍(lán)牙(需要在此之前獲取藍(lán)牙適配器BluetoothAdapter 才可以 調(diào)起打開藍(lán)牙)

?2.1.1 獲取藍(lán)牙適配器BluetoothAdapter

BluetoothManager bluetoothManager =

(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter = bluetoothManager.getAdapter();

??2.1.2 權(quán)限申請(qǐng)成功后 就可以?打開藍(lán)牙 ,如下是藍(lán)牙是

if(mBluetoothAdapter ==null|| !mBluetoothAdapter.isEnabled()) {

Intent enableBtIntent =newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT);

}

2.2 掃描藍(lán)牙設(shè)備

mBluetoothAdapter.startLeScan(mLeScanCallback)

需要注意:搜索是一個(gè)不間斷的搜索過程,需要我們手動(dòng) 停止搜索

所以需要 調(diào)用mBluetoothAdapter. mBluetoothAdapter.stopLeScan(mLeScanCallback);

具體代碼?定時(shí)搜索 如下

private voidscanLeDevice(final booleanenable) {

if(enable) {

// Stops scanning after a pre-defined scan period.

mHandler.postDelayed(newRunnable() {

@Override

public voidrun() {

mScanning =false;

mBluetoothAdapter.stopLeScan(mLeScanCallback);

}

},SCAN_PERIOD);

mScanning =true;

mBluetoothAdapter.startLeScan(mLeScanCallback);

}else{

mScanning =false;

mBluetoothAdapter.stopLeScan(mLeScanCallback);

}

關(guān)于mLeScanCallback的具體實(shí)現(xiàn)

privateBluetoothAdapter.LeScanCallback mLeScanCallback =

newBluetoothAdapter.LeScanCallback() {

@Override

public voidonLeScan(finalBluetoothDevice device, intrssi,

byte[] scanRecord) {

//搜索到藍(lán)牙 將會(huì)在該方法回調(diào) , device就是搜索到的藍(lán)牙

}

};

注意:藍(lán)牙搜索過程 是沒有幫我們過來重復(fù)搜索到藍(lán)牙 ,如果想要把搜索結(jié)果放在集合返回,有可能一個(gè)設(shè)備會(huì)重復(fù)給搜索到,這個(gè)時(shí)候需要自己做個(gè)過濾,可通過bleDevice 的mac 地址不同進(jìn)行過濾

2. 連接藍(lán)牙流程

2.1 先理清 將會(huì)常操作的幾個(gè) 類的概念?如下是它們的關(guān)系流程圖

BluetoothGatt:手機(jī)與BLE終端設(shè)備建立通信的一個(gè)管道,只有有了這個(gè)管道,之后的所有讀寫通知操作都是通過這個(gè)來操作

BluetoothGattService:藍(lán)牙設(shè)備的服務(wù),每個(gè)BluetoothGatt有多個(gè)BluetoothGattService,在這里我們把BluetoothGattService比喻成班級(jí)。而Bluetoothdevice我們把它比喻成學(xué)校,一個(gè)學(xué)校里面可以有很多班級(jí),也就是說我們每臺(tái)BLE終端設(shè)備擁有多個(gè)服務(wù),班級(jí)(各個(gè)服務(wù))之間通過UUID(唯一標(biāo)識(shí)符)區(qū)別

BluetoothGattCharacteristic:藍(lán)牙所擁有的特征 。每個(gè)BluetoothGattService有多個(gè)BluetoothGattCharacteristic。它是手機(jī)與BLE終端設(shè)備交換數(shù)據(jù)的關(guān)鍵,我們做的所有事情,目的就是為了得到它。在這里我們把它比喻成學(xué)生,一個(gè)班級(jí)里面有很多個(gè)學(xué)生,也就是說我們每個(gè)服務(wù)下?lián)碛卸鄠€(gè)特征,學(xué)生(各個(gè)特征)之間通過UUID(唯一標(biāo)識(shí)符)區(qū)別。

理清了我們開始連接藍(lán)牙

2.2連接藍(lán)牙

搜索到藍(lán)牙后?拿到藍(lán)牙對(duì)象 BluetoothDevice device 調(diào)用如下方法

參數(shù):第一個(gè)參數(shù)是上下文對(duì)象,第二個(gè)參數(shù)是是否自動(dòng)連接,這里設(shè)置為false,第三個(gè)參數(shù)就是上面的回調(diào)方法

mBluetoothGatt = device.connectGatt(this, false,mGattCallback);

mGattCallback的具體實(shí)現(xiàn)

privateBluetoothGattCallbackmGattCallback=newBluetoothGattCallback() {

//連接狀態(tài)改變的回調(diào)

@Override

public voidonConnectionStateChange(BluetoothGatt gatt, intstatus,

intnewState) {

if(newState == BluetoothProfile.STATE_CONNECTED) {

// 連接成功后 必須啟調(diào)用 服務(wù)發(fā)現(xiàn) (discoverServices)

//調(diào)用后 當(dāng)回調(diào) onServicesDiscovered(BluetoothGatt gatt, int status)方法

//才屬于真正的成功連接

mBluetoothGatt.discoverServices();

}

}

//發(fā)現(xiàn)服務(wù)的回調(diào)

public voidonServicesDiscovered(BluetoothGatt gatt, intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"成功發(fā)現(xiàn)服務(wù)");

}else{

Log.e(TAG,"服務(wù)發(fā)現(xiàn)失敗,錯(cuò)誤碼為:"+ status);

}

if(status == BluetoothGatt.GATT_SUCCESS) {

if(mBluetoothGatt !=null&& isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_NOTIFICATION);

booleanb = mBluetoothGatt.setCharacteristicNotification(characteristic, true);

if(b) {

List descriptors = characteristic.getDescriptors();

for(BluetoothGattDescriptor descriptor : descriptors) {

booleanb1 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);

if(b1) {

mBluetoothGatt.writeDescriptor(descriptor);

Log.d(TAG,"startRead: "+"監(jiān)聽收數(shù)據(jù)");

}

}

}

}

}

//寫操作的回調(diào)

public voidonCharacteristicWrite (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic,intstatus){

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"寫入成功"+ characteristic.getValue());

}

}

//讀操作的回調(diào)

public voidonCharacteristicRead (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic,intstatus){

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"讀取成功"+ characteristic.getValue());

}

}

//數(shù)據(jù)返回的回調(diào)(此處接收BLE設(shè)備返回?cái)?shù)據(jù))

public voidonCharacteristicChanged (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic){

}

}

}

當(dāng) 回調(diào)? onServicesDiscovered(BluetoothGatt gatt, int status) 方法 后? 就可以拿著? ? gatt(上文有解釋概念) 進(jìn)行 讀寫通知 操作了

3 關(guān)于 讀,寫,通知,操作

?寫數(shù)據(jù)

public void?startSend(View view) {

if?(mBluetoothGatt !=?null?&& isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_WRITE);

byte[] bytes =?new byte[2];

bytes[0] =?04;

bytes[1] =?01;

characteristic.setValue(bytes);

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

mBluetoothGatt.writeCharacteristic(characteristic);

}}

寫入成功會(huì)回調(diào)

public void?onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int?status) {

if?(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,?"寫入成功"?+characteristic.getValue());

}

}

讀數(shù)據(jù)

public void?startSend(View view) {

if?(mBluetoothGatt !=?null?&& isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_WRITE);

byte[] bytes =?new byte[2];

bytes[0] =?04;

bytes[1] =?01;

characteristic.setValue(bytes);

mBluetoothGatt.readCharacteristic(characteristic);

}

}

讀取成功會(huì)回調(diào)

//讀操作的回調(diào)

public voidonCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"讀取成功"+characteristic.getValue());

}

}

注意: 在 讀寫操作過程? 不可以 用for 一次性進(jìn)行操作? 會(huì)出現(xiàn)阻塞? 需要 將讀寫操作 寫入 隊(duì)列中? 一個(gè)一個(gè)寫入? 才是比較好的操作? 也不會(huì)出現(xiàn)堵塞問題

? 藍(lán)牙的操作流程? 就此結(jié)束? ? 在此基礎(chǔ)上? 可以再次封裝一層? 代碼就不出來了,一下是流程圖



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

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

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