Android4.3 藍牙BLE初步

1、關鍵概念:

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。
 

2、角色和職責:

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端可能更合適。
 
 

3、權限及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();
}
 
 

4、啓動藍牙:

在使用藍牙BLE以前,須要確認Android設備是否支持BLE feature(required爲false時),另外要須要確認藍牙是否打開。 
若是發現不支持BLE,則不能使用BLE相關的功能。若是支持BLE,可是藍牙沒打開,則須要打開藍牙。
 
打開藍牙的步驟:
 
一、獲取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)。
 
二、判斷是否支持藍牙,並打開藍牙
 
獲取到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);
}
 
 

5、搜索BLE設備:

經過調用BluetoothAdapter的 startLeScan()搜索BLE設備。調用此方法時須要傳入  BluetoothAdapter.LeScanCallback參數。
所以你須要實現  BluetoothAdapter.LeScanCallback接口,BLE設備的搜索結果將經過這個callback返回。
 
因爲搜索須要儘可能減小功耗,所以在實際使用時須要注意:
 
一、當找到對應的設備後,當即中止掃描;
二、不要循環搜索設備,爲每次搜索設置適合的時間限制。避免設備不在可用範圍的時候持續不停掃描,消耗電量。
 
搜索的示例代碼以下:
/**
 * 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設備,二者徹底獨立,不可同時被搜索。
 
 

6、鏈接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。
 
等等。
 
注:
一、某些函數調用之間存在前後關係。例如首先須要connect上才能discoverServices。
二、 一些函數調用是異步的,須要獲得的值不會當即返回,而會在BluetoothGattCallback的回調函數中返回。例如 discoverServices與onServicesDiscovered回調,readCharacteristic與 onCharacteristicRead回調,setCharacteristicNotification與 onCharacteristicChanged回調等。
 
http://www.blogjava.net/zh-weir/archive/2014/04/02/407373.html
相關文章
相關標籤/搜索