近來工作做了很多Android手機對接藍牙設備的工作,記錄一下。
場景
需要對接藍牙設備,發送或者獲取數據,比如藍牙打印機、藍牙體脂稱、藍牙電子血壓計、藍牙血糖儀、藍牙身高尺等等。大致的過程就是手機跟設備互相連接認證,互傳數據的過程。當然,對接不同的設備,會有不同的交互流程,同一類設備,針對不同廠商,也需要遵循不同廠商定制的SDK的相關協議。但都離不開藍牙的核心協議,下面分經典藍牙2.0以及低功耗藍牙4.0(BLE)。
經典藍牙2.0
比較傳統的設備只支持藍牙2.0,SPP協議、HDP協議
過程:掃描,配對,連接,通信
參考:Android 藍牙開發基本流程
1、通用UUID:
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
2、配對,反射設置密碼(如果需要設置的話)
Method removeBondMethod = btClass.getDeclaredMethod("setPin", new Class[] { byte[].class });
return value = (Boolean) removeBondMethod.invoke(bluetoothDevice, new Object[] { password.getBytes() });
3、配對,反射調用綁定方法
Method createBondMethod = btClass.getMethod("createBond");
Boolean value = (Bovolean) createBondMethod.invoke(btDevice);
4、連接,根據不同SDK方式
問題:getBluetoothService() called with no BluetoothManagerCallback
int sdk = Build.VERSION.SDK_INT;
if (sdk >= 10) {
socket = mDevice.createInsecureRfcommSocketToServiceRecord(SPP_UUID);
} else {
socket = mDevice.createRfcommSocketToServiceRecord(SPP_UUID);
}
低功耗藍牙4.0技術(BLE)
注意:從Android4.3(API-18)開始支持BLE,但只支持作為中心設備模式Central,也就是只支持Android設備主動掃描連接外圍設備Peripheral,在Android5.0(API-21)兩種模式都支持。藍牙4.0將三種規格集一體,包括傳統藍牙技術、高速技術和低耗能技術
參考:最全最詳細的藍牙版本介紹包含藍牙4.0和4.1
過程:掃描,連接,發現服務,通信
1、獲取BluetoothAdapter
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
2、判斷是否支持藍牙,并打開藍牙(利用系統Intent的方式請求打開藍牙)
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
3、搜索BLE設備
mBluetoothAdapter.startLeScan(mLeScanCallback);
BluetoothAdapter.LeScanCallback // 搜索回調
注意:搜索時,你只能搜索傳統藍牙設備或者BLE設備,兩者完全獨立,不可同時被搜索。
實際使用:使用經典藍牙搜索方式startDiscovery()能同時搜索到百捷2.0和百捷4.0的設備
4、連接GATT Server
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
BluetoothGattCallback // 連接回調
5、連接成功。BluetoothGatt常規用到的幾個操作示例
connect(); // 連接遠程設備。
discoverServices(); // 搜索連接設備所支持的service。
disconnect(); // 斷開與遠程設備的GATT連接。
close(); // 關閉GATT Client端。
readCharacteristic(characteristic); // 讀取指定的characteristic。
setCharacteristicNotification(characteristic, enabled); // 設置當指定characteristic值變化時,發出通知。
getServices(); // 獲取遠程設備所支持的services。
一些實踐心得
關于藍牙硬件
對接藍牙設備,一方面由于藍牙設備的多樣性,另一方面Android手機硬件、系統的多樣性,會遇到比較多的問題就是藍牙連接的穩定性問題。關于這個問題也是嘗試了很多種方法去避免,分析其中一個原因就是:由代碼驅動藍牙硬件的過程,需要一定的時間,一定的時間等待,會帶來極大穩定性的提高。比如啟動藍牙后延遲300ms在執行其他操作。另一個就是可以采用線程輪詢判斷一個狀態是否已經啟動,比如循環5次,每隔1秒執行判斷操作。
關于優化
必要時,考慮采用服務Service去獲取設備的數據,或者設置單例模式。
如有錯誤,歡迎拍磚!