在我的上兩篇博文中講解了有關android藍芽的認識以及API的相關的介紹,藍芽BLE的搜尋,連線以及讀取。
沒有了解的童鞋們請參考:
目前專案中的效果圖:
接下來我們就對藍芽BLE4.0進行一下總結。
藍芽API
Android ble 藍芽4.0,也就是說API level >= 18,且支援藍芽4.0的手機才可以使用,如果手機系統版本API level < 18,也是用不了藍芽4.0的哦
BluetoothGatt
繼承BluetoothProfile,通過BluetoothGatt可以連線裝置(connect),發現服務(discoverServices),並把相應地屬性返回到BluetoothGattCallback
BluetoothGattCharacteristic
相當於一個資料型別,它包括一個value和0~n個value的描述(BluetoothGattDescriptor)
BluetoothGattDescriptor
描述符,對Characteristic的描述,包括範圍、計量單位等
BluetoothGattService
服務,Characteristic的集合。
BluetoothProfile
一個通用的規範,按照這個規範來收發資料。
BluetoothManager
通過BluetoothManager來獲取BluetoothAdapter
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);複製程式碼
BluetoothAdapter
一個Android系統只有一個BluetoothAdapter ,通過BluetoothManager 獲取
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter(); 1.8 BluetoothGattCallback複製程式碼
已經連線上裝置,對裝置的某些操作後返回的結果。這裡必須提醒下,已經連線上裝置後的才可以返回,沒有返回的認真看看有沒有連線上裝置。
private BluetoothGattCallback GattCallback = new BluetoothGattCallback() { // 這裡有9個要實現的方法,看情況要實現那些,用到那些就實現那些 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){}; public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){}; }; BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); BluetoothGatt gatt = device.connectGatt(this, false, mGattCallback);複製程式碼
notification對應onCharacteristicChanged
gatt.setCharacteristicNotification(characteristic, true);複製程式碼
readCharacteristic對應onCharacteristicRead
gatt.readCharacteristic(characteristic);複製程式碼
- writeCharacteristic對應onCharacteristicWrite
gatt.wirteCharacteristic(mCurrentcharacteristic);複製程式碼
連線藍芽或者斷開藍芽 對應 onConnectionStateChange
readDescriptor對應onDescriptorRead;
writeDescriptor對應onDescriptorWrite;
gatt.writeDescriptor(descriptor);複製程式碼
- readRemoteRssi對應onReadRemoteRssi
gatt.readRemoteRssi()複製程式碼
executeReliableWrite對應onReliableWriteCompleted;
discoverServices對應onServicesDiscovered
gatt.discoverServices()複製程式碼
- BluetoothDevice
掃描後發現可連線的裝置,獲取已經連線的裝置二、開啟藍芽許可權
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>複製程式碼
Android ble 藍芽4.0,也就是說API level >= 18,且支援藍芽4.0的手機才可以使用,如果手機系統版本API level < 18,也是用不了藍芽4.0的
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "裝置不支援藍芽4.0", Toast.LENGTH_SHORT).show();
finish();
}複製程式碼
或者是
// 檢查當前手機是否支援blue 藍芽,如果不支援退出程式
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
showToast("不支援藍芽4.0通訊");
return;
}
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// 檢查裝置上是否支援藍芽
if (mBluetoothAdapter == null) {
showToast("沒有發現藍芽模組");
return;
}複製程式碼
三、對藍芽的啟動關閉操作
- isEnabled()
如果本地藍芽處在可用狀態(例如手機藍芽開啟)就返回true
- getState()
獲得藍芽狀態 一般有BluetoothAdapter.STATE_BLE_ON ,STATE_BLE_TURNING_ON ,STATE_BLE_TURNING_OFF ,STATE_OFF
- enable()
開啟藍芽裝置,這種方式不友好,建議使用下面方法
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(intent,OPEN_REQUEST_CODE);複製程式碼
這樣會有個彈窗提示使用者是否開啟藍芽
- disable()
關閉所有的藍芽連線後關閉本地藍芽服務
- getAddress()
獲得藍芽mac地址
- getName()
獲得藍芽名稱,也就收我們經常設定的藍芽名稱
- setName()
設定藍芽名稱
- startDiscovery()
開始發現裝置(注意是裝置,例如另外一個手機,而不是藍芽耳機之類的)
- getBondedDevices()
獲取繫結(配對)的裝置,測試發現只有手動取消繫結才管用,否則即使關閉藍芽,間隔一會再開啟,這些仍然是繫結的.
同時一些繫結的裝置(例如手環)用這個方法並沒有返回對應的device - startLeScan(LeScanCallback)
開始對Bluetooth LE devices裝置(藍芽耳機,手環,電子稱等)的掃描.回撥函式會把掃描到的裝置返回,
注意裝置會重複被掃描到,最好去掉重複,去重時可以用mac地址,也可以用名稱,但是掃描到的Device第一次沒有把
名稱帶回,所以獲取名稱時最好做非空判斷 - stopLeScan(LeScanCallback)
停止掃描
利用系統預設開啟藍芽對話方塊
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }複製程式碼
Android藍芽服務的相關類簡介之BluetoothGatt
Generic Attribute Profile (GATT)—The GATT profile is a general specification for sending and receiving short
pieces of data known as "attributes" over a BLE link. All current Low Energy application profiles are based on
GATT.主從裝置都維護了GATT 分別是client 和 server
獲得方法,建立連線時返回
mConnGatt = bleDevie.connectGatt(this, false, mGattcallback);複製程式碼
回撥
public abstract class BluetoothGattCallback {
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
}
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
}複製程式碼
設定通知
public boolean setCharacteristicNotification(UUID serviceUuid, UUID characteristicUuid, boolean enable) {
BluetoothGattCharacteristic characteristic = mConnGatt.getService(serviceUuid).getCharacteristic(characteristicUuid);
mConnGatt.setCharacteristicNotification(characteristic, enable);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[]{0x00, 0x00});
return mConnGatt.writeDescriptor(descriptor); // descriptor write
}複製程式碼
曾經遇到的坑
藍芽接連時超時
解決方法:
在廣播中相應的方法裡進行重新連線private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {//藍芽已連線 tvBluetooth.setText("(已連線)"); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { showToast("藍芽連線斷開,請重試"); //這裡重新連線藍芽 hideLoading(); } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {//發現藍芽,設定命令 ...... } else if(BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //接收到資料 ...... } } };複製程式碼
藍芽搜尋進行匹配不來BLE裝置
有些手效能比較低端,這裡可以重啟藍芽,進行重新連線
連線成功後斷開
- 保證BLE小裝置沒有被其他連線
- 先停止掃描---》重新掃描---》重新連線
讀取過程中藍芽斷開
首先要保證連線藍芽之前,上一次斷開連線時的操作:
- 斷開連線
- 斷開(關閉)service
- 關閉藍芽
然後執行:
先停止掃描---》重新掃描---》重新連線上傳資料失敗
把讀取到的資料解析後進行儲存在本地,下次上傳的時候一起上傳。上傳成功後記得進行本低資料的清空
注意:BLE藍芽連線小裝置時一般屬於主從模組,其中主模組藍芽可以同時連線多個裝置,但讀取時只能讀取一個。
- 主機:可主動搜尋從機,可以傳送資料,也可以接收資料
- 從機:可以傳送資料,也可以接收資料,但只能被搜尋
有關專案下載地址: download.csdn.net/detail/lqw7…
GitHub下載連結:github.com/androidstar…
接下來推薦兩個關於Android藍芽BLE的學習網址:
詳細解析BluetoothAdapter的詳細api
www.open-open.com/lib/view/op…
Android:藍芽4.0-BLE-小結=1.0
如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部
(歡迎關注學習和交流)