Android BLE基礎操做框架,基於回調,操做簡單。包含掃描、多鏈接、廣播包解析、服務讀寫及通知等功能。android
項目地址:github.com/xiaoyaoyou1…git
項目依賴:compile 'com.vise.xiaoyaoyou:baseble:2.0.0'
github
支持多設備鏈接管理;正則表達式
支持廣播包解析;算法
支持自定義掃描過濾條件;bash
支持根據設備名稱正則表達式過濾掃描設備;框架
支持根據設備信號最小值過濾掃描設備;ide
支持根據設備名稱或 MAC 地址列表過濾掃描設備;學習
支持根據設備 UUID 過濾掃描設備;gradle
支持根據指定設備名稱或 MAC 地址搜索指定設備;
支持鏈接設備失敗重試;
支持操做設備數據失敗重試;
支持綁定數據收發通道,同一種能力可綁定多個通道;
支持註冊和取消通知監聽;
支持配置最大鏈接數,超過最大鏈接數時會依據 Lru 算法自動斷開最近最久未使用設備;
支持配置掃描、鏈接和操做數據超時時間;
支持配置鏈接和操做數據重試次數以及重試間隔時間。
打造該庫的目的是爲了簡化藍牙設備接入的流程。該庫是 BLE 操做的基礎框架,只處理 BLE 設備通訊邏輯,不包含具體的數據處理,如數據的分包與組包等。該庫提供了多設備鏈接管理,可配置最大鏈接數量,並在超過最大鏈接數時會依據 Lru 算法自動斷開最近最久未使用設備。該庫還定製了經常使用的掃描設備過濾規則,也支持自定義過濾規則。該庫全部操做都採用回調機制告知上層調用的結果,操做簡單,接入方便。
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 以上手機使用了模糊定位功能,因此須要添加模糊定位權限。
在工程 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) {
}
});複製代碼
bluetoothLeDevice.getName()
;bluetoothLeDevice.getAddress()
;bluetoothLeDevice.getBluetoothDeviceClassName()
;bluetoothLeDevice.getBluetoothDeviceMajorClassName()
;bluetoothLeDevice.getBluetoothDeviceKnownSupportedServices()
;bluetoothLeDevice.getBluetoothDeviceBondState()
;bluetoothLeDevice.getFirstTimestamp()
;bluetoothLeDevice.getFirstRssi()
;bluetoothLeDevice.getTimestamp()
;bluetoothLeDevice.getRssi()
;bluetoothLeDevice.getRunningAverageRssi()
;根據掃描到的廣播包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,如:開始掃描與中止掃描、鏈接與斷開鏈接、清除資源等,該庫提供的功能儘可能簡單易用,這也正是該項目的宗旨。