Android BLE基礎框架全新改版

Android BLE基礎操做框架,基於回調,操做簡單。包含掃描、多鏈接、廣播包解析、服務讀寫及通知等功能。android

功能

  • 支持多設備鏈接管理;正則表達式

  • 支持廣播包解析;算法

  • 支持自定義掃描過濾條件;bash

  • 支持根據設備名稱正則表達式過濾掃描設備;框架

  • 支持根據設備信號最小值過濾掃描設備;ide

  • 支持根據設備名稱或 MAC 地址列表過濾掃描設備;學習

  • 支持根據設備 UUID 過濾掃描設備;gradle

  • 支持根據指定設備名稱或 MAC 地址搜索指定設備;

  • 支持鏈接設備失敗重試;

  • 支持操做設備數據失敗重試;

  • 支持綁定數據收發通道,同一種能力可綁定多個通道;

  • 支持註冊和取消通知監聽;

  • 支持配置最大鏈接數,超過最大鏈接數時會依據 Lru 算法自動斷開最近最久未使用設備;

  • 支持配置掃描、鏈接和操做數據超時時間;

  • 支持配置鏈接和操做數據重試次數以及重試間隔時間。

簡介

打造該庫的目的是爲了簡化藍牙設備接入的流程。該庫是 BLE 操做的基礎框架,只處理 BLE 設備通訊邏輯,不包含具體的數據處理,如數據的分包與組包等。該庫提供了多設備鏈接管理,可配置最大鏈接數量,並在超過最大鏈接數時會依據 Lru 算法自動斷開最近最久未使用設備。該庫還定製了經常使用的掃描設備過濾規則,也支持自定義過濾規則。該庫全部操做都採用回調機制告知上層調用的結果,操做簡單,接入方便。

效果展現

BLE效果
BLE效果

使用介紹

權限配置

6.0 如下系統不須要配置權限,庫中已經配置了以下權限:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>複製代碼

而若是手機系統在 6.0 以上則須要配置以下權限:

<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>複製代碼

由於藍牙在 6.0 以上手機使用了模糊定位功能,因此須要添加模糊定位權限。

引入 SDK

在工程 module 的 build.gradle 文件中的 dependencies 中添加以下依賴:

compile 'com.vise.xiaoyaoyou:baseble:2.0.0'複製代碼

構建完後就能夠直接使用該庫的功能了。

初始化

在使用該庫前須要進行初始化,初始化代碼以下所示:

//藍牙相關配置修改
ViseBle.config()
        .setScanTimeout(-1)//掃描超時時間,這裏設置爲永久掃描
        .setConnectTimeout(10 * 1000)//鏈接超時時間
        .setOperateTimeout(5 * 1000)//設置數據操做超時時間
        .setConnectRetryCount(3)//設置鏈接失敗重試次數
        .setConnectRetryInterval(1000)//設置鏈接失敗重試間隔時間
        .setOperateRetryCount(3)//設置數據操做失敗重試次數
        .setOperateRetryInterval(1000)//設置數據操做失敗重試間隔時間
        .setMaxConnectCount(3);//設置最大鏈接設備數量
//藍牙信息初始化,全局惟一,必須在應用初始化時調用
ViseBle.getInstance().init(this);複製代碼

初始化能夠是在 Application 中也能夠是在 MainActivity 中,只須要是在使用藍牙功能前就行。還有須要注意的是,藍牙配置必須在藍牙初始化前進行修改,若是默認配置知足要求也能夠不修改配置。

設備掃描

庫中針對設備掃描定義了幾種經常使用過濾規則,若是不知足要求也能夠本身定義過濾規則,下面針對庫中提供的過濾規則使用方式一一介紹:

  • 掃描全部設備

    ViseBle.getInstance().startScan(new ScanCallback(new IScanCallback() {
      @Override
      public void onDeviceFound(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanFinish(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanTimeout() {
    
      }
    }));複製代碼
  • 掃描指定設備 MAC 的設備

    //該方式是掃到指定設備就中止掃描
    ViseBle.getInstance().startScan(new SingleFilterScanCallback(new IScanCallback() {
      @Override
      public void onDeviceFound(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanFinish(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanTimeout() {
    
      }
    }).setDeviceMac(deviceMac));複製代碼
  • 掃描指定設備名稱的設備

    //該方式是掃到指定設備就中止掃描
    ViseBle.getInstance().startScan(new SingleFilterScanCallback(new IScanCallback() {
      @Override
      public void onDeviceFound(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanFinish(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanTimeout() {
    
      }
    }).setDeviceName(deviceName));複製代碼
  • 掃描指定 UUID 的設備

    ViseBle.getInstance().startScan(new UuidFilterScanCallback(new IScanCallback() {
      @Override
      public void onDeviceFound(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanFinish(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanTimeout() {
    
      }
    }).setUuid(uuid));複製代碼
  • 掃描指定設備 MAC 或名稱集合的設備

    ViseBle.getInstance().startScan(new ListFilterScanCallback(new IScanCallback() {
      @Override
      public void onDeviceFound(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanFinish(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanTimeout() {
    
      }
    }).setDeviceMacList(deviceMacList).setDeviceNameList(deviceNameList));複製代碼
  • 掃描指定信號範圍或設備正則名稱的設備

    ViseBle.getInstance().startScan(new RegularFilterScanCallback(new IScanCallback() {
      @Override
      public void onDeviceFound(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanFinish(BluetoothLeDeviceStore bluetoothLeDeviceStore) {
    
      }
    
      @Override
      public void onScanTimeout() {
    
      }
    }).setDeviceRssi(rssi).setRegularDeviceName(regularDeviceName));複製代碼

其中掃描到的設備列表由 BluetoothLeDeviceStore 管理,而單個設備信息都統一放到BluetoothLeDevice中,其中包含了設備的全部信息,如設備名稱、設備地址、廣播包解析信息等,設備的相關信息會在設備詳情中進行介紹。

設備鏈接

設備鏈接有三種方式,一種是根據設備信息直接進行鏈接,另外兩種是在沒掃描的狀況下直接經過設備名稱或設備 MAC 進行掃描鏈接。三種鏈接方式使用以下:

  • 根據設備信息鏈接設備

    ViseBle.getInstance().connect(bluetoothLeDevice, new IConnectCallback() {
      @Override
      public void onConnectSuccess(DeviceMirror deviceMirror) {
    
      }
    
      @Override
      public void onConnectFailure(BleException exception) {
    
      }
    
      @Override
      public void onDisconnect(boolean isActive) {
    
      }
    });複製代碼
  • 根據設備 MAC 直接掃描並鏈接

    ViseBle.getInstance().connectByMac(deviceMac, new IConnectCallback() {
      @Override
      public void onConnectSuccess(DeviceMirror deviceMirror) {
    
      }
    
      @Override
      public void onConnectFailure(BleException exception) {
    
      }
    
      @Override
      public void onDisconnect(boolean isActive) {
    
      }
    });複製代碼
  • 根據設備名稱直接掃描並鏈接

    ViseBle.getInstance().connectByName(deviceName, new IConnectCallback() {
      @Override
      public void onConnectSuccess(DeviceMirror deviceMirror) {
    
      }
    
      @Override
      public void onConnectFailure(BleException exception) {
    
      }
    
      @Override
      public void onDisconnect(boolean isActive) {
    
      }
    });複製代碼

設備詳情

DEVICE INFO(設備信息)

  • 獲取設備名稱(Device Name):bluetoothLeDevice.getName()
  • 獲取設備地址(Device Address):bluetoothLeDevice.getAddress()
  • 獲取設備類別(Device Class):bluetoothLeDevice.getBluetoothDeviceClassName()
  • 獲取主要設備類別(Major Class):bluetoothLeDevice.getBluetoothDeviceMajorClassName()
  • 獲取服務類別(Service Class):bluetoothLeDevice.getBluetoothDeviceKnownSupportedServices()
  • 獲取配對狀態(Bonding State):bluetoothLeDevice.getBluetoothDeviceBondState()

RSSI INFO(信號信息)

  • 獲取第一次信號時間戳(First Timestamp):bluetoothLeDevice.getFirstTimestamp()
  • 獲取第一次信號強度(First RSSI):bluetoothLeDevice.getFirstRssi()
  • 獲取最後一次信號時間戳(Last Timestamp):bluetoothLeDevice.getTimestamp()
  • 獲取最後一次信號強度(Last RSSI):bluetoothLeDevice.getRssi()
  • 獲取平均信號強度(Running Average RSSI):bluetoothLeDevice.getRunningAverageRssi()

SCAN RECORD INFO(廣播信息)

根據掃描到的廣播包AdRecordStore獲取某個廣播數據單元AdRecord的類型編號record.getType(),再根據編號獲取廣播數據單元的類型描述record.getHumanReadableType()以及該廣播數據單元的長度及數據內容,最後經過AdRecordUtil.getRecordDataAsString(record)將數據內容轉換成具體字符串。更多關於廣播包解析能夠參考Android BLE學習筆記中數據解析部分。

發送數據

在發送數據前須要先綁定寫入數據通道,綁定通道的同時須要設置寫入數據的回調監聽,具體代碼示例以下:

BluetoothGattChannel bluetoothGattChannel = new BluetoothGattChannel.Builder()
        .setBluetoothGatt(deviceMirror.getBluetoothGatt())
        .setPropertyType(PropertyType.PROPERTY_WRITE)
        .setServiceUUID(serviceUUID)
        .setCharacteristicUUID(characteristicUUID)
        .setDescriptorUUID(descriptorUUID)
        .builder();
deviceMirror.bindChannel(new IBleCallback() {
    @Override
    public void onSuccess(byte[] data, BluetoothGattChannel bluetoothGattChannel, BluetoothLeDevice bluetoothLeDevice) {

    }

    @Override
    public void onFailure(BleException exception) {

    }
}, bluetoothGattChannel);
deviceMirror.writeData(data);複製代碼

這裏的 deviceMirror 在設備鏈接成功後就能夠獲取到,須要注意的是,服務同樣的狀況下寫入數據的通道只須要註冊一次,若是寫入數據的通道有多個則能夠綁定多個。寫入數據必需要在綁定寫入數據通道後進行,能夠在不一樣的地方屢次寫入。

接收數據

與發送數據同樣,接收設備發送的數據也須要綁定接收數據通道,這裏有兩種方式,一種是可通知方式、一種是指示器方式,使用方式以下:

  • 可通知方式

    BluetoothGattChannel bluetoothGattChannel = new BluetoothGattChannel.Builder()
          .setBluetoothGatt(deviceMirror.getBluetoothGatt())
          .setPropertyType(PropertyType.PROPERTY_NOTIFY)
          .setServiceUUID(serviceUUID)
          .setCharacteristicUUID(characteristicUUID)
          .setDescriptorUUID(descriptorUUID)
          .builder();
    deviceMirror.bindChannel(new IBleCallback() {
      @Override
      public void onSuccess(byte[] data, BluetoothGattChannel bluetoothGattChannel, BluetoothLeDevice bluetoothLeDevice) {
    
      }
    
      @Override
      public void onFailure(BleException exception) {
    
      }
    }, bluetoothGattChannel);
    deviceMirror.registerNotify(false);複製代碼
  • 指示器方式

    BluetoothGattChannel bluetoothGattChannel = new BluetoothGattChannel.Builder()
          .setBluetoothGatt(deviceMirror.getBluetoothGatt())
          .setPropertyType(PropertyType.PROPERTY_INDICATE)
          .setServiceUUID(serviceUUID)
          .setCharacteristicUUID(characteristicUUID)
          .setDescriptorUUID(descriptorUUID)
          .builder();
    deviceMirror.bindChannel(new IBleCallback() {
      @Override
      public void onSuccess(byte[] data, BluetoothGattChannel bluetoothGattChannel, BluetoothLeDevice bluetoothLeDevice) {
    
      }
    
      @Override
      public void onFailure(BleException exception) {
    
      }
    }, bluetoothGattChannel);
    deviceMirror.registerNotify(true);複製代碼

    在綁定通道後須要註冊通知,並須要在收到註冊成功的回調時調用以下代碼設置監聽:

    deviceMirror.setNotifyListener(bluetoothGattInfo.getGattInfoKey(), new IBleCallback() {
      @Override
      public void onSuccess(byte[] data, BluetoothGattChannel bluetoothGattChannel, BluetoothLeDevice bluetoothLeDevice) {
    
      }
    
      @Override
      public void onFailure(BleException exception) {
    
      }
    });複製代碼

    全部設備發送過來的數據都會經過上面的監聽獲得,若是不想監聽也能夠取消註冊,使用方式以下:

    deviceMirror.unregisterNotify(isIndicate);複製代碼

    isIndicate 表示是不是指示器方式。

讀取數據

因爲讀取設備信息基本每次的通道都不同,因此這裏與上面收發數據有點不同,每次讀取數據都須要綁定一次通道,使用示例以下:

BluetoothGattChannel bluetoothGattChannel = new BluetoothGattChannel.Builder()
        .setBluetoothGatt(deviceMirror.getBluetoothGatt())
        .setPropertyType(PropertyType.PROPERTY_READ)
        .setServiceUUID(serviceUUID)
        .setCharacteristicUUID(characteristicUUID)
        .setDescriptorUUID(descriptorUUID)
        .builder();
deviceMirror.bindChannel(new IBleCallback() {
    @Override
    public void onSuccess(byte[] data, BluetoothGattChannel bluetoothGattChannel, BluetoothLeDevice bluetoothLeDevice) {

    }

    @Override
    public void onFailure(BleException exception) {

    }
}, bluetoothGattChannel);
deviceMirror.readData();複製代碼

總結

從以上的描述中能夠知道,設備相關的全部操做都統一交給 ViseBle 進行處理,而且該類是單例模式,全局只有一個,管理很方便。使用該庫提供的功能前必需要調用 ViseBle.getInstance().init(context); 進行初始化。每鏈接成功一款設備都會在設備鏡像池中添加一款設備鏡像,該設備鏡像是維護設備鏈接成功後全部操做的核心類,在斷開鏈接時會將該設備鏡像從鏡像池中移除,若是鏈接設備數量超過配置的最大鏈接數,那麼設備鏡像池會依據 Lru 算法自動移除最近最久未使用設備並斷開鏈接。ViseBle 中封裝了幾個經常使用的 API,如:開始掃描與中止掃描、鏈接與斷開鏈接、清除資源等,該庫提供的功能儘可能簡單易用,這也正是該項目的宗旨。

相關文章
相關標籤/搜索