一、關鍵概念:
Generic
Attribute Profile (GATT)
通過BLE連接,讀寫屬性類小數據的Profile通用規範。現在所有的BLE應用Profile都是基於GATT的。
Attribute
Protocol (ATT)
GATT是基於ATT
Protocol的。ATT針對BLE設備做了專門的優化,具體就是在傳輸過程中使用盡量少的數據。每個屬性都有一個唯一的UUID,屬性將以characteristics and services的形式傳輸。
Characteristic
Characteristic可以理解爲一個數據類型,它包括一個value和0至多個對次value的描述(Descriptor)。
Descriptor
對Characteristic的描述,例如範圍、計量單位等。
Service
Characteristic的集合。例如一個service叫做“Heart
Rate Monitor”,它可能包含多個Characteristics,其中可能包含一個叫做“heart rate measurement"的Characteristic。
二、角色和職責:
Android設備與BLE設備交互有兩組角色:
中心設備和外圍設備(Central
vs. peripheral);
GATT
server vs. GATT client.
Central
vs. peripheral:
中心設備和外圍設備的概念針對的是BLE連接本身。Central角色負責scan
advertisement。而peripheral角色負責make advertisement。
GATT
server vs. GATT client:
這兩種角色取決於BLE連接成功後,兩個設備間通信的方式。
舉例說明:
現有一個活動追蹤的BLE設備和一個支持BLE的Android設備。Android設備支持Central角色,而BLE設備支持peripheral角色。創建一個BLE連接需要這兩個角色都存在,都僅支持Central角色或者都僅支持peripheral角色則無法建立連接。
當連接建立後,它們之間就需要傳輸GATT數據。誰做server,誰做client,則取決於具體數據傳輸的情況。例如,如果活動追蹤的BLE設備需要向Android設備傳輸sensor數據,則活動追蹤器自然成爲了server端;而如果活動追蹤器需要從Android設備獲取更新信息,則Android設備作爲server端可能更合適。
三、權限及feature:
和經典藍牙一樣,應用使用藍牙,需要聲明BLUETOOTH權限,如果需要掃描設備或者操作藍牙設置,則還需要BLUETOOTH_ADMIN權限:
<uses-permission
android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
除了藍牙權限外,如果需要BLE
feature則還需要聲明uses-feature:
<uses-feature
android:name="android.hardware.bluetooth_le" android:required="true"/>
按時required爲true時,則應用只能在支持BLE的Android設備上安裝運行;required爲false時,Android設備均可正常安裝運行,需要在代碼運行時判斷設備是否支持BLE
feature:
//
Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
四、啓動藍牙:
在使用藍牙BLE之前,需要確認Android設備是否支持BLE
feature(required爲false時),另外要需要確認藍牙是否打開。
如果發現不支持BLE,則不能使用BLE相關的功能。如果支持BLE,但是藍牙沒打開,則需要打開藍牙。
打開藍牙的步驟:
1、獲取BluetoothAdapter
BluetoothAdapter是Android系統中所有藍牙操作都需要的,它對應本地Android設備的藍牙模塊,在整個系統中BluetoothAdapter是單例的。當你獲取到它的示例之後,就能進行相關的藍牙操作了。
獲取BluetoothAdapter代碼示例如下:
//
Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
注:這裏通過getSystemService獲取BluetoothManager,再通過BluetoothManager獲取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API
level 18)。
2、判斷是否支持藍牙,並打開藍牙
獲取到BluetoothAdapter之後,還需要判斷是否支持藍牙,以及藍牙是否打開。
如果沒打開,需要讓用戶打開藍牙:
private
BluetoothAdapter mBluetoothAdapter;
...
// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
五、搜索BLE設備:
通過調用BluetoothAdapter的startLeScan()搜索BLE設備。調用此方法時需要傳入BluetoothAdapter.LeScanCallback參數。
因此你需要實現 BluetoothAdapter.LeScanCallback接口,BLE設備的搜索結果將通過這個callback返回。
由於搜索需要儘量減少功耗,因此在實際使用時需要注意:
1、當找到對應的設備後,立即停止掃描;
2、不要循環搜索設備,爲每次搜索設置適合的時間限制。避免設備不在可用範圍的時候持續不停掃描,消耗電量。
搜索的示例代碼如下:
/**
* Activity for scanning and displaying available BLE devices.
*/
public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
...
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
...
}
...
}
如果你只需要搜索指定UUID的外設,你可以調用 startLeScan(UUID[],
BluetoothAdapter.LeScanCallback)方法。
其中UUID數組指定你的應用程序所支持的GATT
Services的UUID。
BluetoothAdapter.LeScanCallback的實現示例如下:
private
LeDeviceListAdapter mLeDeviceListAdapter;
...
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
注意:搜索時,你只能搜索傳統藍牙設備或者BLE設備,兩者完全獨立,不可同時被搜索。
六、連接GATT Server:
兩個設備通過BLE通信,首先需要建立GATT連接。這裏我們講的是Android設備作爲client端,連接GATT
Server。
連接GATT
Server,你需要調用BluetoothDevice的connectGatt()方法。此函數帶三個參數:Context、autoConnect(boolean)和BluetoothGattCallback對象。調用示例:
mBluetoothGatt
= device.connectGatt(this, false, mGattCallback);
函數成功,返回BluetoothGatt對象,它是GATT
profile的封裝。通過這個對象,我們就能進行GATT Client端的相關操作。BluetoothGattCallback用於傳遞一些連接狀態及結果。
BluetoothGatt常規用到的幾個操作示例:
connect()
:連接遠程設備。
discoverServices()
: 搜索連接設備所支持的service。
disconnect():斷開與遠程設備的GATT連接。
close():關閉GATT
Client端。
readCharacteristic(characteristic)
:讀取指定的characteristic。
setCharacteristicNotification(characteristic,
enabled) :設置當指定characteristic值變化時,發出通知。
getServices()
:獲取遠程設備所支持的services。
等等。
注:
1、某些函數調用之間存在先後關係。例如首先需要connect上才能discoverServices。
2、一些函數調用是異步的,需要得到的值不會立即返回,而會在BluetoothGattCallback的回調函數中返回。例如discoverServices與onServicesDiscovered回調,readCharacteristic與onCharacteristicRead回調,setCharacteristicNotification與onCharacteristicChanged回調等。
Android4.3 藍牙BLE初步
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
Android開發之ButterKnife,GreenDao簡單運用,以及推薦並使用一個好用的開源庫BaseRecyclerViewAdapterHelper。
不要说话丶
2018-08-27 20:04:11
nexus 5X update 8.0
杨飞扬
2018-08-27 20:04:03
Retrofit2 使用心得
杨飞扬
2018-08-27 20:03:51
Android studio Errors
杨飞扬
2018-08-27 20:03:48
Summary of problems when coding
杨飞扬
2018-08-27 20:03:48
Android Studio 配置Android Annotation
杨飞扬
2018-08-27 20:03:48
Android內存管理機制
叫我流氓
2018-08-27 20:03:47
2018 Android面試心得,已拿到offer
huison_ma
2018-08-27 20:03:45
Android中的dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()
叫我流氓
2018-08-27 20:03:44
Android滑動衝突解決方式(下拉刷新上拉加載更多,適配RecyclerView/ListView/ScrollView)
huison_ma
2018-08-27 20:03:44
Activity生命週期基礎
叫我流氓
2018-08-27 20:03:44
短信監聽---數據庫變動
叫我流氓
2018-08-27 20:03:44
Android應用程序框架四大重要的組件
叫我流氓
2018-08-27 20:03:44
Android studio 打包jar包
叫我流氓
2018-08-27 20:03:44
SQLite---T_double
叫我流氓
2018-08-27 20:03:43
24小時熱門文章
-
再談23種設計模式(3):行爲型模式(學習筆記)
-
Power Automate Desktop 安裝完,登錄後老是提示one driver 錯誤
-
微前端學習筆記(4):從微前端到微模塊之EMP與hel-micro方案探索
-
微前端學習筆記(1):微前端總體架構概述,從微服務發微
-
985 碩士程序員,空窗 4 個月沒有 Offer!
-
一文搞懂 Spring 循環依賴
-
賽博鬥地主——使用大語言模型扮演Agent智能體玩牌類遊戲。
-
VScode右鍵打開(添加到右鍵)
-
記一次 .NET某工控視覺自動化系統 卡死分析
-
WindowsServer--SQL Server搭建主從同步實現讀寫分離 - 事務性分發