???這篇博客的作用是為了讓小白朋友了解andorid藍(lán)牙的一些基本概念,同時(shí)學(xué)習(xí)總結(jié)下目前我實(shí)際項(xiàng)目中用到的藍(lán)牙庫 BluetoothKit ,包括其優(yōu)點(diǎn) 霹肝、基本使用位仁,最后以庫中的源碼為基石深入探究這個(gè)優(yōu)秀的藍(lán)牙庫的設(shè)計(jì)理念痴晦。
???
一 . 藍(lán)牙基礎(chǔ)知識(shí):
1宙地、BLE藍(lán)牙的基本介紹
1.1BLe藍(lán)牙介紹
Android 4.3(API Level 18)開始引入Bluetooth Low Energy(BLE像鸡,低功耗藍(lán)牙)的核心功能并提供了相應(yīng)的 API, 應(yīng)用程序通過這些 API 掃描藍(lán)牙設(shè)備分冈、查詢 services、讀寫設(shè)備的 characteristics(屬性特征)等操作霸株。
Android BLE 使用的藍(lán)牙協(xié)議是 GATT 協(xié)議雕沉,有關(guān)該協(xié)議的詳細(xì)內(nèi)容可以參見藍(lán)牙官方文檔或者這篇博客(https://blog.csdn.net/u013378580/article/details/52891462)。以下我引用一張官網(wǎng)的圖來大概說明 Android 開發(fā)中我們 用到的一些專業(yè)術(shù)語去件。(專業(yè)名詞參考1.2節(jié)內(nèi)容)
1.2坡椒、Android BLE的相關(guān)系統(tǒng)API
Profile
一個(gè)通用的規(guī)范,即Ble的藍(lán)牙通訊協(xié)議尤溜,Ble藍(lán)牙的必須按照這個(gè)規(guī)范來收發(fā)數(shù)據(jù)倔叼。
Service
一個(gè)低功耗藍(lán)牙設(shè)備可以定義許多 Service, Service 可以理解為一個(gè)功能的集合。設(shè)備中每一個(gè)不同的 Service 都有一個(gè) 128 bit 的 UUID 作為這個(gè) Service 的獨(dú)立標(biāo)志宫莱。藍(lán)牙核心規(guī)范制定了兩種不同的UUID丈攒,一種是基本的UUID,一種是代替基本UUID的16位UUID授霸。所有的藍(lán)牙技術(shù)聯(lián)盟定義UUID共用了一個(gè)基本的UUID:0x0000xxxx-0000-1000-8000-00805F9B34FB 為了進(jìn)一步簡化基本UUID巡验,每一個(gè)藍(lán)牙技術(shù)聯(lián)盟定義的屬性有一個(gè)唯一的16位UUID,以代替上面的基本UUID的‘x’部分碘耳。例如显设,心率測(cè)量特性使用0X2A37作為它的16位UUID,因此它完整的128位UUID為: 0x00002A37-0000-1000-8000-00805F9B34FB
BluetoothAdapter
BluetoothAdapter 擁有系統(tǒng)調(diào)用藍(lán)牙基本的藍(lán)牙操作辛辨,例如開啟藍(lán)牙掃描 連接捕捂,使用已知的 MAC 地址 (BluetoothAdapter#getRemoteDevice)實(shí)例化一個(gè) BluetoothDevice 用于連接藍(lán)牙設(shè)備的操作等等。
BluetoothDevice
代表一個(gè)遠(yuǎn)程藍(lán)牙設(shè)備愉阎。這個(gè)類可以讓你連接所代表的藍(lán)牙設(shè)備或者獲取一些有關(guān)它的信息绞蹦,例如它的名字,地址和綁定狀態(tài)等等榜旦。
RSSI
Received Signal Strength Indication.用來標(biāo)識(shí)搜索到的設(shè)備的信號(hào)強(qiáng)度值幽七。
BluetoothGatt
這個(gè)類提供了 Bluetooth GATT 的基本功能。例如重新連接藍(lán)牙設(shè)備溅呢,發(fā)現(xiàn)藍(lán)牙設(shè)備的 Service 等等澡屡,是在一個(gè)中心設(shè)備(如手機(jī))和外圍設(shè)備(手環(huán)等Ble設(shè)備)之間建立的數(shù)據(jù)通道,通過調(diào)用gatt對(duì)象的一系列方法來操作藍(lán)牙咐旧。
UUID
一個(gè)service對(duì)應(yīng)一個(gè)UUID
一藍(lán)牙核心規(guī)范制定了兩種不同的UUID驶鹉,一種是基本的UUID,一種是代替基本UUID的16位UUID铣墨。所有的藍(lán)牙技術(shù)聯(lián)盟定義UUID共用了一個(gè)基本的UUID:0x0000xxxx-0000-1000-8000-00805F9B34FB
為了進(jìn)一步簡化基本UUID室埋,每一個(gè)藍(lán)牙技術(shù)聯(lián)盟定義的屬性有一個(gè)唯一的16位UUID,以代替上面的基本UUID的‘x’部分。例如姚淆,心率測(cè)量特性使用0X2A37作為它的16位UUID孕蝉,因此它完整的128位UUID為:0x00002A37-0000-1000-8000-00805F9B34FB
BluetoothGattService
一個(gè)低功耗藍(lán)牙設(shè)備可以定義許多 Service, Service 可以理解為一個(gè)功能的集合。設(shè)備中每一個(gè)不同的 Service 都有一個(gè) 128 bit 的 UUID 作為這個(gè) Service 的獨(dú)立標(biāo)志腌逢。
這一個(gè)類通過 BluetoothGatt#getService 獲得降淮,如果當(dāng)前服務(wù)不可見那么將返回一個(gè) null。這一個(gè)類對(duì)應(yīng)上面說過的 Service搏讶。我們可以通過這個(gè)類的 getCharacteristic(UUID uuid) 進(jìn)一步獲取 Characteristic 實(shí)現(xiàn)藍(lán)牙數(shù)據(jù)的雙向傳輸佳鳖。
BluetoothGattCharacteristic
在 Service之下,又包括了許多的獨(dú)立數(shù)據(jù)項(xiàng)媒惕,我們把這些獨(dú)立的數(shù)據(jù)項(xiàng)稱作 Characteristic系吩。同樣的,每一個(gè) Characteristic 也有一個(gè)唯一的 UUID 作為標(biāo)識(shí)符吓笙。在 Android 開發(fā)中淑玫,建立藍(lán)牙連接后巾腕,我們說的通過藍(lán)牙發(fā)送數(shù)據(jù)給外圍設(shè)備就是往這些 Characteristic 中的 Value 字段寫入數(shù)據(jù)面睛;外圍設(shè)備發(fā)送數(shù)據(jù)給手機(jī)就是監(jiān)聽這些 Charateristic 中的 Value 字段有沒有變化,如果發(fā)生了變化尊搬,手機(jī)的 BLE API 就會(huì)收到一個(gè)監(jiān)聽的回調(diào)叁鉴。
這個(gè)類對(duì)應(yīng)上面提到的 Characteristic。通過這個(gè)類定義需要往外圍設(shè)備寫入的數(shù)據(jù)和讀取外圍設(shè)備發(fā)送過來的數(shù)據(jù)佛寿,這個(gè)類是中心設(shè)備和BLE設(shè)備之間數(shù)據(jù)通信的載體幌墓。
相當(dāng)于一個(gè)數(shù)據(jù)類型,它包括一個(gè)value和0~n個(gè)value的描述(BluetoothGattDescriptor)
BluetoothGattDescriptor
Characteristic之下,描述符冀泻,對(duì)Characteristic的描述常侣,包括范圍、計(jì)量單位等
Notification和Indication
Notification 外圍設(shè)備(硬件)設(shè)備給中心設(shè)備(手機(jī))發(fā)送一個(gè)數(shù)據(jù),無需接收方確認(rèn)弹渔。接收通知
Indication 外圍設(shè)備給中心設(shè)備(手機(jī))發(fā)送一個(gè)數(shù)據(jù),需要接收方確認(rèn)胳施。二者關(guān)系類似于TCP協(xié)議和UDP協(xié)議,效率上來講Notification比Indication要高肢专。在藍(lán)牙API中體現(xiàn)在notify() 方法和indicate()方法舞肆。
1.3與傳統(tǒng)藍(lán)牙ClassicBluetooth的比較
1.3.1藍(lán)牙模塊分類
1.3.2BLE和CLASSIC藍(lán)牙的比較
經(jīng)典藍(lán)牙模塊(BT):泛指支持藍(lán)牙協(xié)議在4.0以下的模塊,一般用于數(shù)據(jù)量比較大的傳輸博杖,如:語音椿胯、音樂、較高數(shù)據(jù)量傳輸?shù)忍旮=?jīng)典藍(lán)牙模塊可再細(xì)分為:傳統(tǒng)藍(lán)牙模塊和高速藍(lán)牙模塊哩盲。傳統(tǒng)藍(lán)牙模塊在2004年推出,主要代表是支持藍(lán)牙2.1協(xié)議的模塊,在智能手機(jī)爆發(fā)的時(shí)期得到廣泛支持廉油。高速藍(lán)牙模塊在2009年推出镣丑,速率提高到約24Mbps,是傳統(tǒng)藍(lán)牙模塊的八倍娱两,可以輕松用于錄像機(jī)至高清電視莺匠、PC至PMP、UMPC至打印機(jī)之間的資料傳輸十兢。
低功耗藍(lán)牙模塊(BLE):是指支持藍(lán)牙協(xié)議4.0或更高的模塊趣竣,也稱為BLE模塊(BluetoohLow EnergyModule),最大的特點(diǎn)是成本和功耗的降低旱物,應(yīng)用于實(shí)時(shí)性要求比較高遥缕,但是數(shù)據(jù)速率比較低的產(chǎn)品,如:遙控類的(鼠標(biāo)宵呛、鍵盤)单匣、傳感設(shè)備的數(shù)據(jù)發(fā)送(心跳帶、血壓計(jì)宝穗、溫度傳感器)等户秤。
接下來是第2個(gè)部分 ,實(shí)際工作中我們使用到的藍(lán)牙庫 BluetoothKit的使用:
二 . 框架介紹:
1.框架項(xiàng)目地址
https://github.com/dingjikerbo/BluetoothKit
2.框架優(yōu)點(diǎn)
一、統(tǒng)一解決Android藍(lán)牙通信過程中的兼容性問題
二逮矛、提供盡可能簡單易用的接口鸡号,屏蔽藍(lán)牙通信中的技術(shù)細(xì)節(jié),只開放連接须鼎,讀寫鲸伴,通知等語義。
三晋控、實(shí)現(xiàn)串行化任務(wù)隊(duì)列汞窗,統(tǒng)一處理藍(lán)牙通信中的失敗以及超時(shí),支持可配置的容錯(cuò)處理
四赡译、統(tǒng)一管理連接句柄仲吏,避免句柄泄露
五、方便監(jiān)控各設(shè)備連接狀態(tài)捶朵,在盡可能維持連接的情況下蜘矢,將最不活躍的設(shè)備自動(dòng)斷開。
六综看、便于多進(jìn)程APP架構(gòu)下藍(lán)牙連接的統(tǒng)一管理
七品腹、支持?jǐn)r截所有對(duì)藍(lán)牙原生接口的調(diào)用
3.基本使用
1.添加依賴compile 'com.inuker.bluetooth:library:1.4.0' 或直接導(dǎo)入依賴Liabrary模塊
2.在app模塊的Manifest中添加藍(lán)牙權(quán)限
<!--藍(lán)牙相關(guān)權(quán)限-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
2. 掃描
BluetoothClient mClient = new BluetoothClient(context);
SearchRequest request = new SearchRequest.Builder()
.searchBluetoothLeDevice(3000, 3) // 先掃BLE設(shè)備3次,每次3s
.searchBluetoothClassicDevice(5000) // 再掃經(jīng)典藍(lán)牙5s,在實(shí)際工作中沒用到經(jīng)典藍(lán)牙的掃描
.searchBluetoothLeDevice(2000) // 再掃BLE設(shè)備2s
.build();
mClient.search(request, new SearchResponse() {
@Override
public void onSearchStarted() {//開始搜素
}
@Override
public void onDeviceFounded(SearchResult device) {//找到設(shè)備 可通過manufacture過濾
Beacon beacon = new Beacon(device.scanRecord);
BluetoothLog.v(String.format("beacon for %s\n%s", device.getAddress(), beacon.toString()));
}
@Override
public void onSearchStopped() {//搜索停止
}
@Override
public void onSearchCanceled() {//搜索取消
}
});
4.2連接
可以配置連接參數(shù)如下红碑,
BleConnectOptions options = new BleConnectOptions.Builder()
.setConnectRetry(3) // 連接如果失敗重試3次
.setConnectTimeout(30000) // 連接超時(shí)30s
.setServiceDiscoverRetry(3) // 發(fā)現(xiàn)服務(wù)如果失敗重試3次
.setServiceDiscoverTimeout(20000) // 發(fā)現(xiàn)服務(wù)超時(shí)20s
.build();
mClient.connect(MAC, options, new BleConnectResponse() {
@Override
public void onResponse(int code, BleGattProfile data) {
}
});
監(jiān)聽連接狀態(tài):
mClient.registerConnectStatusListener(MAC, mBleConnectStatusListener);
private final BleConnectStatusListener mBleConnectStatusListener = new BleConnectStatusListener() {
@Override
public void onConnectStatusChanged(String mac, int status) {
if (status == STATUS_CONNECTED) {
} else if (status == STATUS_DISCONNECTED) {
}
}
};
mClient.unregisterConnectStatusListener(MAC, mBleConnectStatusListener);
4.3 通訊
**讀Characteristic**
mClient.read(MAC, serviceUUID, characterUUID, new BleReadResponse() {
@Override
public void onResponse(int code, byte[] data) {
if(code == REQUEST_SUCCESS) {
}
}
});
**寫Characteristic**
要注意這里寫的byte[]不能超過20字節(jié)舞吭,如果超過了需要自己分成幾次寫泡垃。建議的辦法是第一個(gè)byte放剩余要寫的字節(jié)的長度。
mClient.write(MAC, serviceUUID, characterUUID, bytes, new BleWriteResponse() {
@Override
public void onResponse(int code) {
if(code == REQUEST_SUCCESS) {
}
}
});
這個(gè)寫是帶了WRITE_TYPE_NO_RESPONSE標(biāo)志的羡鸥,實(shí)踐中發(fā)現(xiàn)比普通的write快2~3倍蔑穴,建議用于固件升級(jí)。
mClient.writeNoRsp(MAC, serviceUUID, characterUUID, bytes, new BleWriteResponse() {
@Override
public void onResponse(int code) {
if(code == REQUEST_SUCCESS) {
}
}
});
**讀Descriptor**
mClient.readDescriptor(MAC, serviceUUID, characterUUID, descriptorUUID, new BleReadResponse() {
@Override
public void onResponse(int code, byte[] data) {
}
});
**寫Descriptor**
mClient.writeDescriptor(MAC, serviceUUID, characterUUID, descriptorUUID, bytes, new BleWriteResponse() {
@Override
public void onResponse(int code) {
}
});
**打開Notify**
這里有兩個(gè)回調(diào)惧浴,onNotify是接收通知的存和。
mClient.notify(MAC, serviceUUID, characterUUID, new BleNotifyResponse() {
@Override
public void onNotify(UUID service, UUID character, byte[] value) {
}
@Override
public void onResponse(int code) {
if(code == REQUEST_SUCCESS) {
}
}
});
**關(guān)閉Notify**
mClient.unnotify(MAC, serviceUUID, characterUUID, new BleUnnotifyResponse() {
@Override
public void onResponse(int code) {
if(code == REQUEST_SUCCESS) {
}
}
});
**打開Indicate**
和Notify類似,
mClient.indicate(MAC, serviceUUID, characterUUID, new BleNotifyResponse() {
@Override
public void onNotify(UUID service, UUID character, byte[] value) {
}
@Override
public void onResponse(int code) {
if(code == REQUEST_SUCCESS) {
}
}
});
**關(guān)閉Indicate**
mClient.unindicate(MAC, serviceUUID, characterUUID, new BleUnnotifyResponse() {
@Override
public void onResponse(int code) {
if(code == REQUEST_SUCCESS) {
}
}
});
**讀Rssi**
mClient.readRssi(MAC, new BleReadRssiResponse() {
@Override
public void onResponse(int code, Integer rssi) {
if(code == REQUEST_SUCCESS) {
}
}
});
4.4 斷開
mClient.disconnect(MAC);
3.藍(lán)牙框架源碼解析
接下來 , 我以藍(lán)牙框架的"連接"功能為例來追蹤下源碼
@Override
public void connect(String mac, BleConnectOptions options, BleConnectResponse response) {
BluetoothLog.v(String.format("connect %s", mac));
response = ProxyUtils.getUIProxy(response);
mClient.connect(mac, options, response);
}
1.BluetoothClientImpl 在這個(gè)實(shí)現(xiàn)里真正干了BluetoothClient的活
@Override
public void connect(String mac, BleConnectOptions options, final BleConnectResponse response) {
Bundle args = new Bundle();
args.putString(EXTRA_MAC, mac);
args.putParcelable(EXTRA_OPTIONS, options);
safeCallBluetoothApi(CODE_CONNECT, args, new BluetoothResponse() {
@Override
protected void onAsyncResponse(int code, Bundle data) {
checkRuntime(true);
if (response != null) {
data.setClassLoader(getClass().getClassLoader());
BleGattProfile profile = data.getParcelable(EXTRA_GATT_PROFILE);
response.onResponse(code, profile);
}
}
});
}
其中有一個(gè)關(guān)鍵方法 safeCallBluetoothApi
private void safeCallBluetoothApi(int code, Bundle args, final BluetoothResponse response) {
checkRuntime(true);
// BluetoothLog.v(String.format("safeCallBluetoothApi code = %d", code));
try {
IBluetoothService service = getBluetoothService();
// BluetoothLog.v(String.format("IBluetoothService = %s", service));
if (service != null) {
args = (args != null ? args : new Bundle());
service.callBluetoothApi(code, args, response);
} else {
response.onResponse(SERVICE_UNREADY, null);
}
} catch (Throwable e) {
BluetoothLog.e(e);
}
}
在這個(gè)方法里,首先拿到了藍(lán)牙的service(通過bindservice的方法),再調(diào)用了callBluetoothApi的方法
接下來我們來重點(diǎn)看下 BluetoothServiceImpl 中的callBluetoothApi方法 :
@Override
public void callBluetoothApi(int code, Bundle args, final IResponse response) throws RemoteException {
Message msg = mHandler.obtainMessage(code, new BleGeneralResponse() {
@Override
public void onResponse(int code, Bundle data) {
if (response != null) {
if (data == null) {
data = new Bundle();
}
try {
response.onResponse(code, data);
} catch (Throwable e) {
BluetoothLog.e(e);
}
}
}
});
args.setClassLoader(getClass().getClassLoader());
msg.setData(args);
msg.sendToTarget();
}
這里面用了handler發(fā)送消息,在handleMessage方法中處理消息 :
@Override
public boolean handleMessage(Message msg) {
Bundle args = msg.getData();
String mac = args.getString(EXTRA_MAC);
UUID service = (UUID) args.getSerializable(EXTRA_SERVICE_UUID);
UUID character = (UUID) args.getSerializable(EXTRA_CHARACTER_UUID);
UUID descriptor = (UUID) args.getSerializable(EXTRA_DESCRIPTOR_UUID);
byte[] value = args.getByteArray(EXTRA_BYTE_VALUE);
BleGeneralResponse response = (BleGeneralResponse) msg.obj;
switch (msg.what) {
case CODE_CONNECT:
BleConnectOptions options = args.getParcelable(EXTRA_OPTIONS);
BleConnectManager.connect(mac, options, response);
break;
case CODE_DISCONNECT:
BleConnectManager.disconnect(mac);
break;
case CODE_READ:
BleConnectManager.read(mac, service, character, response);
break;
case CODE_WRITE:
BleConnectManager.write(mac, service, character, value, response);
break;
case CODE_WRITE_NORSP:
BleConnectManager.writeNoRsp(mac, service, character, value, response);
break;
case CODE_READ_DESCRIPTOR:
BleConnectManager.readDescriptor(mac, service, character, descriptor, response);
break;
case CODE_WRITE_DESCRIPTOR:
BleConnectManager.writeDescriptor(mac, service, character, descriptor, value, response);
break;
case CODE_NOTIFY:
BleConnectManager.notify(mac, service, character, response);
break;
case CODE_UNNOTIFY:
BleConnectManager.unnotify(mac, service, character, response);
break;
case CODE_READ_RSSI:
BleConnectManager.readRssi(mac, response);
break;
case CODE_SEARCH:
SearchRequest request = args.getParcelable(EXTRA_REQUEST);
BluetoothSearchManager.search(request, response);
break;
case CODE_STOP_SESARCH:
BluetoothSearchManager.stopSearch();
break;
case CODE_INDICATE:
BleConnectManager.indicate(mac, service, character, response);
break;
case CODE_REQUEST_MTU:
int mtu = args.getInt(EXTRA_MTU);
BleConnectManager.requestMtu(mac, mtu, response);
break;
case CODE_CLEAR_REQUEST:
int clearType = args.getInt(EXTRA_TYPE, 0);
BleConnectManager.clearRequest(mac, clearType);
break;
case CODE_REFRESH_CACHE:
BleConnectManager.refreshCache(mac);
break;
}
return true;
}
handleMessage方法中首先解析了bundle,然后區(qū)分不同的CODE處理不同的操作,針對(duì)"連接"的connect方法,接下來追蹤到BleConnectMaster.connect方法
@Override
public void connect(BleConnectOptions options, BleGeneralResponse response) {
getConnectDispatcher().connect(options, response);
}
以上可以看出通過拿到dispatcher這個(gè)分發(fā)類來處理任務(wù),跳轉(zhuǎn)到dispatcher中的addNewRequest方法 ,
private void addNewRequest(BleRequest request) {
checkRuntime();
if (mBleWorkList.size() < MAX_REQUEST_COUNT) { //最多的請(qǐng)求數(shù)是100
request.setRuntimeChecker(this);
request.setAddress(mAddress);
request.setWorker(mWorker);//將worker設(shè)置為request,worker才是真正干活的
mBleWorkList.add(request);
} else {
request.onResponse(Code.REQUEST_OVERFLOW);
}
scheduleNextRequest(10);
}
scheduleNextRequest中通過handler發(fā)送了一個(gè)延時(shí)消息,消息處理的過程中調(diào)用了scheduleNextRequest()方法
private void scheduleNextRequest(long delayInMillis) {
mHandler.sendEmptyMessageDelayed(MSG_SCHEDULE_NEXT, delayInMillis);
}
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_SCHEDULE_NEXT:
scheduleNextRequest();
break;
}
return true;
}
private void scheduleNextRequest() {
if (mCurrentRequest != null) {
return;
}
if (!ListUtils.isEmpty(mBleWorkList)) {
mCurrentRequest = mBleWorkList.remove(0);
//以下為重要代碼
mCurrentRequest.process(this);
}
}
其中有一行關(guān)鍵的代碼 mCurrentRequest.process(this),接下來我們看下BleRequest 到底是怎么干活的?
@Override
final public void process(IBleConnectDispatcher dispatcher) {
checkRuntime();
mDispatcher = dispatcher;
BluetoothLog.w(String.format("Process %s, status = %s", getClass().getSimpleName(), getStatusText()));
//兼容性的的判斷
if (!BluetoothUtils.isBleSupported()) {
onRequestCompleted(Code.BLE_NOT_SUPPORTED);
} else if (!BluetoothUtils.isBluetoothEnabled()) {
onRequestCompleted(Code.BLUETOOTH_DISABLED);
} else {
try {
registerGattResponseListener(this);
processRequest();
} catch (Throwable e) {
BluetoothLog.e(e);
onRequestCompleted(Code.REQUEST_EXCEPTION);
}
}
}
這里面有一個(gè)關(guān)鍵的方法, processRequest(),這是一個(gè)抽象方法,子類需要實(shí)現(xiàn)的自己實(shí)現(xiàn),關(guān)于"連接"我們可以追蹤到 BleConnectRequest,以下的方法可以看到,最終判斷現(xiàn)在的連接狀態(tài)后 進(jìn)行連接的回調(diào)
@Override
public void processRequest() {
processConnect();
}
private void processConnect() {
mHandler.removeCallbacksAndMessages(null);
mServiceDiscoverCount = 0;
switch (getCurrentStatus()) {
case Constants.STATUS_DEVICE_CONNECTED://連接成功
processDiscoverService();//處理服務(wù) -- 讀服務(wù)
break;
case Constants.STATUS_DEVICE_DISCONNECTED://連接失敗,打開Gatt
if (!doOpenNewGatt()) {
closeGatt();
} else {
mHandler.sendEmptyMessageDelayed(MSG_CONNECT_TIMEOUT, mConnectOptions.getConnectTimeout());
}
break;
case Constants.STATUS_DEVICE_SERVICE_READY:
onConnectSuccess();
break;
}
}
至此,分析告一段落,現(xiàn)在我們來分析下連接的另一個(gè)關(guān)鍵內(nèi)容 response 回調(diào)的處理,以連接為例,在BleConnectWorker中有一個(gè)連接回調(diào),根據(jù)不同的情況回調(diào)回去.
以上為初學(xué)藍(lán)牙和藍(lán)牙框架的一些感悟,以后有機(jī)會(huì)務(wù)必會(huì)完善此博客~