首先,這個庫是用於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>
在Application里設置
BluetoothContext.set(this);
核心類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,嘗試過在連接的時候把掃描停止了,有好轉,不過並未徹底解決;
4.在部分華為機型上藍牙連接不穩定
5.一定要在Application里設置 BluetoothContext.set(this);
