______________________________________________________________
Android BLE 框架发布,功能全面,简单易用:
https://github.com/a1anwang/okble
______________________________________________________________
可以先看一下另一篇文章 《android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser》
熟悉一下BLE的广播数据
BluetoothLeScanner 是android5.0 新加入的
在5.0之前扫描BLE设备 使用的方法是 :
bluetoothAdapter.startLeScan( leScanCallback);
//或者
// UUID[] serviceUuids = new UUID[] { UUID.fromString("0000ae8f-0000-1000-8000-00805f9b34fb") };
// bluetoothAdapter.startLeScan(serviceUuids, leScanCallback);
private LeScanCallback leScanCallback=new LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothdeivce, int rssi, byte[] scandata) {
//把byte数组转成16进制字符串,方便查看
Log.e("TAG","scandata:"+ Bytes2HexString(scandata) +" rssi:"+rssi);
}};
可以看到,这个扫描方法已经过时了,被划了线
新和扫描方法使用的是BluetoothLeScanner,封装成了一个新的类
那么用法也很简单:
BluetoothLeScanner bluetoothLeScanner=bluetoothAdapter.getBluetoothLeScanner(); bluetoothLeScanner.startScan(scanCallback); private ScanCallback scanCallback=new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { byte[] scanData=result.getScanRecord().getBytes(); //把byte数组转成16进制字符串,方便查看 Log.e("TAG","onScanResult :"+CYUtils.Bytes2HexString(scanData)); Log.e("TAG","onScanResult :"+result.getScanRecord().toString()); } @Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); } @Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); } };BluetoothLeScanner还有另一个扫描方法,这个方法就是多了一个扫描过滤 和 扫描设置参数:
public void startScan(List<ScanFilter> filters, ScanSettings settings, final ScanCallback callback)
我们来看一下BluetoothLeScanner 源码:
发现,startScan(callback) 其实是调用第2个扫描方法,只是 过滤参数为空,设置参数也是默认的。
好,不管怎么样,我们先来看下使用 startScan(callback) 扫描结果是什么样子的, 我手上的设备依然是 使用 BluetoothLeAdvertiser把手机2模拟成BLE来测试的(建议可以先看下我另一篇文章的前半部分,了解一下BLE的广播《android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser》)
模拟的广播的数据依然是:
E/TAG: scandata:02011A05FFAC0134560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000好,那我们开始扫描看一下log打印结果:
05-24 17:01:08.011 19454-19454/jiqi.scandemo E/TAG: onScanResult :02011A05FFAC0134560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 05-24 17:01:08.011 19454-19454/jiqi.scandemo E/TAG: onScanResult :ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={428=[52, 86]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null]可以知道,使用BluetoothLeScanner想要扫描出BLE设备的原始数据,需要通过 result.getScanRecord().getBytes() 来获取 byte[]数组
下面打印的ScanRecord 可以看到 有很多数据:
mManufacturerSpecificData={428=[52, 86]} 这个是设备厂商数据,是AC013456这一段, 通过我另一片文章知道 AC01是倒过来的,其实真实数据是01AC 两个字节,代表厂商id, 16进制数字,那么 0x01AC = 428 16进制的01AC等于10进制的428, 所有通过 log打印出来我们看到的是428,因为android studio 控制台打印默认是10进制,所以我们看到的log是428. 后面的52,86一样的道理 0x34=52, 0x56=86.
还有一些其他数据 如 mServiceUuids,mServerData等等
好了,这样我们就知道了,其实这个新的扫描方法和 旧的差别不大,区别就在于在扫描结果里把原始的 byte[]的广播数据给 解析了,然后封装返回给我们, 是不是google 怕新手解析起来无从下手?(手动滑稽)
接下来 使用一组《android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser》文章里的 广播数据,再打印一下,对比查看就明白了:
使用的广播数据:
E/TAG: scandata:02011A05FFAC0134560303E1FF05168FAE641200000000000000000000000000000000000000000000000000000000000000000000000000000000000000使用BluetoothLeScanner 扫描结果如下:
05-24 17:38:41.731 12596-12596/jiqi.scandemo E/TAG: onScanResult :02011A05FFAC0134560303E1FF05168FAE641200000000000000000000000000000000000000000000000000000000000000000000000000000000000000 05-24 17:38:41.731 12596-12596/jiqi.scandemo E/TAG: onScanResult :ScanRecord [mAdvertiseFlags=26, mServiceUuids=[0000ffe1-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={428=[52, 86]}, mServiceData={0000ae8f-0000-1000-8000-00805f9b34fb=[100, 18]}, mTxPowerLevel=-2147483648, mDeviceName=null]mServiceUuids里面的 0000ffe1...... 这个数据对应于byte[]数组里的 E1FF,mServerData里的 0000ae8f.....=[100,18] 对应于 byte[]数组里的8FAE ,6412
好了,关于扫描结果的解析到此, 下面介绍一下 startScan(List<ScanFilter> filters, ScanSettings settings, final ScanCallback callback) 里面的过滤参数和扫描设置参数
第一个
List<ScanFilter> filters 可以添加多个过滤条件,如下:
可以设置mac地址,还有设备名称,serveruuid,serverdata 等等,这个比 之前的老扫描 代码
BluetoothAdapter. startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) 高级,老代码只能设置一个过滤serveruuid。
当然这都是小问题,老代码在扫描到设备结果里面我们也可以手动写代码来再次过滤。
下面看一下ScanSettings ,
setCallbackType 参数有如下几项: ScanSettings.CALLBACK_TYPE_ALL_MATCHES,CALLBACK_TYPE_FIRST_MATCH, CALLBACK_TYPE_MATCH_LOST
setMatchMode 参数有: ScanSettings.MATCH_MODE_AGGRESSIVE, MATCH_MODE_STICKY
setScanMode 参数有: ScanSettings.SCAN_MODE_OPPORTUNISTIC //这是一个特殊的扫描模式(投机取巧的),就是说程序本身不会使用BLE扫描功能,而是借助其他的扫描结果,比如程序A用了这个模式,其实程序A没有使用到蓝牙功能, 但是程序B在扫描的话,程序B的扫描结果会共享给程序A SCAN_MODE_LOW_POWER,SCAN_MODE_BALANCED,SCAN_MODE_LOW_LATENCY 这三个参数会越来越耗电,但扫描结果会越来越快(扫描结果间隔越来越短)
原文地址《android BLE 扫描BLE设备 BluetoothLeScanner》
发表评论