關於Ble通信庫BluetoothKit的使用 以及可能出現的問題分析
首先,這個庫是用於BLE(低功耗藍牙)通信的,地址:https://github.com/dingjikerbo/BluetoothKit
當然,也可以選擇根據andorid提供的底層接口自己完成這部分的通信,這個庫優點在於確實很方便使用,基本都是回調就能完成。作者好像也是前就職於阿裏?
介紹下用法:
先在gradle加入:
compile ‘com.inuker.bluetooth:library:1.4.0‘
在Menifest中配置:
(ps:在6.0以上需要使用動態權限)
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-feature android:name="android.hardware.bluetooth_le"android:required="true" /> <application android:label="@string/app_name"> <service android:name="com.inuker.bluetooth.library.BluetoothService" /> </application>
核心類BluetoothClient,創建一個這樣的單例對象,可以借用其例子中的ClientManager類
BluetoothClient mClient = new BluetoothClient(context); //自己寫 BluetoothClient mClient = ClientManager.getClient(); //借用作者的ClientManager
一般都需要做個掃描界面來選擇設備吧,這個庫是支持普通藍牙和低功耗藍牙混掃的
SearchRequest request = new SearchRequest.Builder() .searchBluetoothLeDevice(3000, 3) // 先掃BLE設備3次,每次3s .searchBluetoothClassicDevice(5000) // 再掃經典藍牙5s .searchBluetoothLeDevice(2000) // 再掃BLE設備2s .build(); mClient.search(request, new SearchResponse() { @Override public void onSearchStarted() { } @Override public void onDeviceFounded(SearchResult device) {
//發現設備 Beacon beacon = new Beacon(device.scanRecord);
//beacon用於解析廣播 BluetoothLog.v(String.format("beacon for %s\n%s", device.getAddress(), beacon.toString()));
//device對象就包括了設備的mac地址和藍牙名稱 ,將device放在list裏面 按mac地址做唯一區別 } @Override public void onSearchStopped() { //掃描停止 } @Override public void onSearchCanceled() { //掃描取消 } });
手動停止掃描:
mClient.stopSearch();
通過上面的代碼我們可以完成設備的掃描,獲取到掃描結果,也可以得到目標設備的mac地址;
廣播的作用是可以不連接設備,就能夠獲取到設備的一些信息,比如電量或者其他的一些廠家信號;
言歸正傳,我們得到了mac地址就可以連接設備了,通過一些代碼既可以完成連接設備:
//連接參數 BleConnectOptions options = new BleConnectOptions.Builder() .setConnectRetry(2) // 連接如果失敗重試2次 .setConnectTimeout(3000) // 連接超時3s .setServiceDiscoverRetry(2) // 發現服務如果失敗重試3次 .setServiceDiscoverTimeout(2000) // 發現服務超時2s .build(); mClient.connect(MAC, options, new BleConnectResponse() { @Override public void onResponse(int code, BleGattProfile data) { } });
個人建議不能確定雙方通信都及其正常的情況下,是需要設置連接參數的,可以保證連接的成功率。如果要監聽藍牙連接狀態可以註冊回調,只有兩個狀態:連接和斷開,建議把監聽設置放在連接前面。
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);
也可以通過mClient獲取連接狀態:
int status = mClient.getConnectStatus(MAC)
連接成功後一般都要打開notify使能,以便獲得硬件回復的數據:
//打開notify
mClient.notify(MAC, serviceUUID, characterUUID, new BleNotifyResponse() { //是notify的UUID @Override public void onNotify(UUID service, UUID character, byte[] value) { //硬件回復的數據在這裏,統一處理
handleResult(value); } @Override public void onResponse(int code) { if (code == REQUEST_SUCCESS) { //我一般都在打開notify成功後才開始發送數據 } } });
//關閉notify
mClient.unnotify(MAC, serviceUUID, characterUUID, new BleUnnotifyResponse() {
@Override
public void onResponse(int code) {
if (code == REQUEST_SUCCESS) {
}
}
});
寫數據,只有通過mClient.write寫數據才有可能收到notify回來的數據,如果通過writeNoRsp寫是不可能收到的,作者註明writeNoRsp建議用於固件升級:
mClient.write(MAC, serviceUUID, characterUUID, bytes, new BleWriteResponse() { @Override public void onResponse(int code) { if (code == REQUEST_SUCCESS) { } } });
這樣就可以實現write-->notify的讀寫操作了。
說一些我遇到的問題:
1.android6.0以上動態權限不僅需要藍牙相關權限,還需要GPS權限,必須保證GPS也打開,才能正常搜索;
2.連接速度問題,經測試,這個庫在nexus5上連接較慢,底層從發現設備到發現服務有時候甚至需要2,3s左右;
3.部分設備有時候出現 notify 返回 -1,嘗試過在連接的時候把掃描停止了,有好轉,不過並未徹底解決;
關於Ble通信庫BluetoothKit的使用 以及可能出現的問題分析