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,如:开始扫描与中止扫描、链接与断开链接、清除资源等,该库提供的功能尽可能简单易用,这也正是该项目的宗旨。