Android 藍牙開發(2)——低功耗藍牙

低功耗藍牙官方文檔

本文章是參考官網,而後加入本身實踐中的理解完成!沒有看上一篇的讀者,能夠先閱讀一下前一篇,這是一個系列。 官網地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le java

Android 4.3 (API 18 )引入了低功耗藍牙,應用能夠查詢周圍設備、查詢設備的服務、傳輸信息。android

關鍵術語和概念

  • 通用屬性配置文件(GATT Generic Attribute Profile)git

    GATT 配置文件是一種傳輸數據規範,用於在 BLE 鏈路上發送和接受被稱爲屬性的短數據的通用規範。目前全部低功耗應用配置文件基本都是基於 GATTgithub

  • Bluetooth SIG (藍牙技術聯盟)服務器

    是爲低功耗設備定義了許多配置文件。配置文件是設備在特定應用程序中的工做方式的規範。設備能夠實現多個配置文件。例如,設備能夠包含心率監測器和電池水平檢測器。併發

    定義規範的框架

  • 屬性協議(ATT Attribute Protocol)ide

    GATT 是創建在屬性協議(ATT)之上的。也被稱爲 GATT/ATT 。ATT 通過優化,可在 BLE 設備上使用。爲此,它使用了儘量少的字節。每一個屬性由通用惟一標識符(UUID)來惟一標識。ATT 傳輸的屬性被格式化爲 特徵服務優化

  • 特徵ui

    特徵包含單個值和描述特徵值的 0 ~ n 個描述符。特徵值能夠被稱爲類型。相似於類。(是在和 BLE 設備進行通訊的時候主要的操做內容)

  • 描述符

    是用來定義特徵值的已定義屬性。用來描述特徵值的。例如:描述符能夠指定人類可讀的描述,特徵值的可接受範圍或者特徵值特定的度量單位

  • 服務

    服務中包含一系列的特徵值。例如,咱們可使用名爲 「心率監測器」的服務,其中包括"心率測量"等特徵。能夠在 bluetooh.org 上找到基於 GATT 的現有配置文件的服務的列表。

角色和責任

Android 設備和 BLE 設備交互時應用的角色和職責

  • 中央與外圍設備。
  • GATT 服務器和 GATT 客戶端。肯定了兩個設備創建鏈接後如何進行相互通訊

BLE 權限

應用在使用藍牙設備的時候必需要聲明藍牙權限 BLUETOOTH 須要這個權限才能夠進行藍牙通訊,例如:請求鏈接、接受鏈接、和傳輸數據。

若是還須要發現或者操做藍牙設置,則須要聲明 BLUETOOTH_ADMIN 權限。使用這個權限的前提是要有 BLUETOOTH 權限。

若是要聲明咱們的應用僅適用於支持 BLE 的設備,須要清單文件中作以下聲明

<uses-feature android:name = "android.hardware.bluetooth_le" android:required = true />

若是咱們但願咱們的應用程序在不支持 BLE 的設備上也能夠運行的時候,只須要將 true 修改爲 false 就能夠了。

還能夠在代碼中做出判斷

if(!getPackageManager().hasSystemFeature(PackgeManger.FEATURE_BLUETOOTH_LE)){
    // 不支持 BLE 設備
}

BLE 一般和位置有關係,所以還須要聲明位置權限 ACCESS_COARSE_LOCATION 或者 ACCESS_FINE_LOCATION 沒有這些權限掃描將不會返回任何結果。

設置 BLE

  1. 得到 BluetoothAdapter

    BluetoothAdapter 表明設備本身的藍牙適配器,整個系統只有一個藍牙適配器,咱們的應用程序可使用此對象與其交互。

    這裏的獲取方法是經過 BluetoothManager 來獲取的

    BluetoothManager bluetoothManger = getSystemSerive(Context.BULETOOTH_SERVIcE);
    BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
  2. 啓用藍牙設備

    其實這些和普通藍牙的啓動都是同樣的。

    isEnable() 查看當前是否啓用了藍牙

    經過 BluetoothAdapter.ACTION_REQUEST_ENABLE 來啓動

  3. 查找 BLE 設備

    這一點和發現普通的藍牙設備是不同的

    // 經過 Adapter 的 startLeScan(callBack); 方法來開啓掃描
    // 若是咱們有指定的藍牙設備可使用
    sartLeScan(UUID[],BluetoothAdapter.LeScanCallBakc) 經過 UUID 來指定 BLe
    // 這個方法已通過時了,官方文檔最新支持的掃描藍牙的方法是經過一個專門的對象 BluetoothLeScanner 用來開啓掃描低功耗藍牙
    BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
    // 這個方法能夠有參數,用來過濾要掃描的低功耗藍牙的,具體的後面講
    scanner.startScan();

    只能單獨掃描普通藍牙設備或者 BLE 設備,沒有方法同時執行

鏈接到 GATT 服務器

與 BLE 設備通訊,第一步就是要鏈接到它,就是鏈接到該設備的 GATT 服務。使用方法 connectGatt()有三個參數:Context 對象 autoConnect (表示是否在可用的時候本身鏈接到 BLE 設備) 還有一個回調,全部的交互都在這個回調裏面完成。

調用這個方法會返回一個 BluetoothGatt 對象,經過這個對象進行和 BLE 設備的交互。交互的結果會在回調方法中觸發。

public class BluetoothLeService extends Service{
    private final static String TAG = BluetoothLeService.class.getSimpleName();
    private BluetoothManger bluetoothManger;
    private BluetoothAdapter bluetoothAdapter;
    private String bluetoothDeviceAddress;
    private BluetoothGatt bluetoothGatt;
    private int connectionState = STATE_DISCONNECTED;
    
    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNETING = 1;
    private static final int STATE_CONNECTED = 2;
    
    public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
    public final satic String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
    public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";
    
    public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.formString(SampleGattAttributes.HEART_RATE_MEASURMENT);
    
    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback(){
        // 你的中央設備鏈接上 ble 設備後,會回調這個這方法。
        @Override
        public viod onConnectionStateChange(BluetoothGatt gatt,int status,int newState){
            String intenAction;
            if(newState == BluetoothProfile.STATE_CONNECTED){
                intentaction = ACTION_GATT_CONNECTED;
                connectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                // 鏈接上後,緊接着就是要尋找裏面 Service
                bluetoothGatt.discoverServices();
            }else if(newState = BluetoothProfile.STATE_STATE_DISCONNECTED{
                intentAction = ACTION_GATT_DISCONNECTED;
                connectionState = STATE_DISCONNECTED;
                broadcastUpdate(intentAction);
                
            }
           
        }
        @Override
        // service 發現後就會觸發這個方法,而後你就須要找到你和 ble 約定好的 service
        public void onServicesDiscovered(BluetoothGatt gatt,int status){
            if(status == BluetoothGatt.GATT_SUCCESS){
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            }            
        }
		
        public void onCharacteristicREad(。。。){
                         
        } 
        .......
                 
        
        
    }
    
}

當觸發特定的回調的時候,會調用適當的 broadcastUpdate() 輔助方法並向其傳遞操做。具體的數據解析格式是根據配置文件規範執行的(是你和你的BLE 設備共同約定好的規範)

大致的過程當中:開啓鏈接,而後會觸發對應的鏈接回調,而後發現服務,觸發發現服務回調,獲取服務內部的特徵值,對其讀寫命令(和 BLE 共同約束的規範)。就是這麼一個過程,很簡單。

讀 BLE 屬性

一旦咱們的 Android 設備鏈接到了 GATT 服務器並發現了服務,咱們就能夠在支持的位置讀取或者寫入屬性了。

完成後要記得關閉設備 bluetoothGatt.close();

關於藍牙框架的一個庫:https://github.com/Alex-Jerry/Android-BLE

相關文章
相關標籤/搜索