Android蓝牙开发系列文章-扫不到蓝牙设备,你的姿势对了吗?

在写《Android蓝牙开发系列文章-蓝牙音箱连接》时,计划细化出两篇文章,分别是:

关于蓝牙设备类型分类的,这个已经完成了,阅读请点击《Android蓝牙开发系列文章-蓝牙设备类型知多少?》

今天我们要完成的是另外一篇:如何扫描蓝牙设备,怎么快速的、准确的扫描设备。

你也许会问,什么叫准确的扫描设备?难道我们在扫描的时候可以指定要扫描设备吗?

答案是肯定的,让我们慢慢讲来~

目录

1.姿势一:扫描经典蓝牙

2.姿势二:用过时的接口扫描低功耗蓝牙

3.姿势三:用时髦的接口扫描低功耗蓝牙

4.总结



1.姿势一:扫描经典蓝牙

《Android蓝牙开发系列文章-蓝牙设备类型知多少?》中,我们没有提“经典蓝牙”和“低功耗蓝牙”的事儿,这里怎么又冒出了这两个概念?

其实,我们在上一节说的蓝牙设备类型,是从功能角度出发进行定义的一种概念。就是说这个蓝牙设备是个音箱,还是一个鼠标。

而今天说的这两个类型是比较专业化的概念,一般人,我是不告诉他的,谁让你关注了我呢,来,让我告诉你。

经典蓝牙设备:又称为传统蓝牙设备,英文为Classic Bluetooth,主要用于传输数据量比较大的功能传输,例如,蓝牙音箱。

低功耗蓝牙设备:英文为Bluetooth Low Energy,最大的特点是功耗的降低,主要用于实时性要求较高、但数据量不大的产品中,例如,蓝牙灯、蓝牙手环等等。

讲完了这两个概念,我们再来讲两个: 单模设备、双模设备。

单模设备:是指进具有经典蓝牙设备功能或者低功耗蓝牙功能的设备。例如,仅仅具有心率测量功能的手环。

双模设备:是指同时具有经典蓝牙设备功能和低功耗蓝牙功能的设备。例如,既具有心率测量功能,又具有通话功能的手环。再例如,我们现在智能电视的蓝牙遥控器(语音功能使用的是经典蓝牙,按键功能使用的是低功耗蓝牙)。再例如,小米的小爱音箱,它就是典型的双模设备,具有两个mac地址。

在这里要说一下,不是所有的双模设备都是两个mac地址,有的也仅是一个mac地址。我抽空会再写一下蓝牙mac 地址的分类(如果一直这样细化下去,不知道我的蓝牙专题是否要写100+篇?),不知道你是否期待?

讲完了概念,我们接着讲“姿势一”,如果你读过我之前写的蓝牙音箱连接的文章,你应该知道了经典蓝牙设备如何扫描了。

调用BluetoothAdapter::startDiscovery()接口,然后接受广播,从广播中解析出你想要的设备。这种方法扫描出的蓝牙设备不仅仅是只能扫描到经典蓝牙,也会扫描到低功耗蓝牙。如果你要扫描经典蓝牙的话,只能忍受这一个弊端了,因为没有别的招了。

如想了解经典蓝牙设备的扫描,请移步《Android蓝牙开发系列文章-蓝牙音箱连接》。我在这里就不再讲解一遍了。

2.姿势二:用过时的接口扫描低功耗蓝牙

下面开始讲一下经典蓝牙设备的扫描。

第一步,要先申请必要的权限,

    <!--蓝牙权限-->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <!--BLE扫描权限-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!--蓝牙ble feature检查,只有在由此feature的设备上才能安装本应用-->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

我在写demo的过程中发现,静态申请了BLE扫描的权限没有生效,没有扫描到任何设备,经过上网百度获悉,从Android6.0开始需要动态申请位置权限,所以有了如下一段代码:

 private void requestPermission() {
        //动态申请是否有必要看sdk版本哈
        if (Build.VERSION.SDK_INT < 23){return;}
        //判断是否有权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //请求权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        }

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //请求权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        }
    }

 先获取BluetoothAdapter对象,然后调用BluetoothAdapter::startLeScan(LeScanCallback callback)发起设备扫描。

扫码到的设备都会在onLeScan()中拿到。

        //蓝牙编程千古不变:第一行代码
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        Log.d(TAG, "mBluetoothAdapter = " + mBluetoothAdapter);
        //设备回调,扫描到的设备都在onLeScan()中拿到
        private static LeScanCallback mLeScanCallback = new LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
                if(device == null || device.getName() == null || device.getAddress() == null)             {
                    return;
                }
                Log.d(TAG, "onLeScan(), device = " + device.getName() +  "mac = " + device.getAddress() + "rssi = " + rssi);
                for (int i = 0; i < scanRecord.length; i++) {
                    Log.d(TAG, "onLeScan(), device = " + device.getName() + "content = " + scanRecord[i]);
                }
            }
        };
        //调用BluetoothAdapter.startLeScan(LeScanCallback callback)发起设备扫描
        private void startBleScan1() {
            boolean ret = mBluetoothAdapter.startLeScan(mLeScanCallback);
            Log.d(TAG, "startBtScan(),ret = " + ret);
        }

运行一下我们的demo,看一下扫描结果,家里的唯一一个低功耗设备,蓝牙体脂秤,被扫描出来了。

03-16 21:07:32.130 9909-9909/com.atlas.devicefinder D/MainActivity: mBluetoothAdapter = android.bluetooth.BluetoothAdapter@ddeeda9
03-16 21:07:32.131 9909-9909/com.atlas.devicefinder D/MainActivity: mBluetoothLeScanner = android.bluetooth.le.BluetoothLeScanner@e0adf2e
03-16 21:07:34.947 9909-9909/com.atlas.devicefinder D/MainActivity: onClick,View = androidx.appcompat.widget.AppCompatButton{e036fde VFED..C.. ...P.... 0,0-426,144 #7f070042 app:id/bt_start_blescan1}
03-16 21:07:34.970 9909-9909/com.atlas.devicefinder D/MainActivity: startBtScan(),ret = true
03-16 21:07:40.498 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9mac = 08:7C:BE:48:65:ADrssi = -78
03-16 21:07:40.499 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 10
03-16 21:07:40.501 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 9
03-16 21:07:40.503 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 49
03-16 21:07:40.505 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 76
03-16 21:07:40.508 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 83
03-16 21:07:40.509 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 95
03-16 21:07:40.512 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 87
03-16 21:07:40.513 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 95
03-16 21:07:40.515 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 57
03-16 21:07:40.517 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 0
03-16 21:07:40.518 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 0
03-16 21:07:40.519 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 2
03-16 21:07:40.521 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 1
03-16 21:07:40.524 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 6
03-16 21:07:40.526 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 5

因为家里只有一个低功耗蓝牙设备,所以没有扫描出来其他设备(这可不是因为这个接口具有扫描指定设备的功能哈,因为它并没有,不然怎么被废弃了呢)。 

3.姿势三:用时髦的接口扫描低功耗蓝牙

这里将一个时髦的蓝牙扫描接口,BluetoothLeScanner::startScan()。这个接口的定义如下所示,第一个参数就是对扫描到的设备的过滤条件,第二个参数表示的是对本次扫描的设置,第三个参数用于接收扫描结果(如果有过滤条件,则是经过滤后的设备)。

   /**
     * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
     * For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
     * resumed when screen is turned on again. To avoid this, do filetered scanning by
     * using proper {@link ScanFilter}.
     * <p>
     * An app must hold
     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
     * in order to get results.
     *
     * @param filters {@link ScanFilter}s for finding exact BLE devices.
     * @param settings Settings for the scan.
     * @param callback Callback used to deliver scan results.
     * @throws IllegalArgumentException If {@code settings} or {@code callback} is null.
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public void startScan(List<ScanFilter> filters, ScanSettings settings,
            final ScanCallback callback) {
        startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null);
    }

我们先不设置过滤条件,看一下该方法如何使用:

先获取BluetoothLeScanner对象,然后调用其startScan(ScanCallback callback)方法,看到没,就只有一个回调参数。

    //先获取BluetoothLeScanner对象
    private BluetoothLeScanner mBluetoothLeScanner = null;
    mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
    private void startBleScan2() {
        mBluetoothLeScanner.startScan(mScanCallback);
    }
    
    //回调接口
    private static ScanCallback mScanCallback = new ScanCallback() {
        //每扫描到一个BLE设备,就接收到一次回调
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            Log.d(TAG, "onScanResult, result = " + result);

        }
        //批量回调接口
        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
            Log.d(TAG, "onBatchScanResults");

        }
        //扫描失败的回调,可以根据失败的原因执行不同策略,例如,重新扫描或者
        //先停止当前扫描,再重新发起扫描
        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.d(TAG, "onScanFailed, errorCode = " + errorCode);
        }
    };

我们这样搞,会得到一个什么样的扫描结果呢?可以看到除了我家的体脂秤,也扫描到了另外一个BLE设备(反正不是俺家的,不知道谁的)。我还特意把我家的蓝牙音箱打开了,结果可想而知:扫不到~

03-15 20:41:37.946 10425-10425/com.atlas.devicefinder D/MainActivity: mBluetoothAdapter = android.bluetooth.BluetoothAdapter@bc4da35
03-15 20:41:37.947 10425-10425/com.atlas.devicefinder D/MainActivity: mBluetoothLeScanner = android.bluetooth.le.BluetoothLeScanner@74b3eca
03-15 20:41:41.476 10425-10425/com.atlas.devicefinder D/MainActivity: onClick,View = androidx.appcompat.widget.AppCompatButton{e98ee7a VFED..C.. ...P.... 0,288-426,432 #7f070043 app:id/bt_start_blescan2}
03-15 20:41:47.466 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-97, mTimestampNanos=86214200338022}
03-15 20:41:52.332 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86219088416145}
03-15 20:41:56.438 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86223197857185}
03-15 20:41:58.892 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-93, mTimestampNanos=86225651024476}
03-15 20:42:04.863 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-95, mTimestampNanos=86231621502599}
03-15 20:42:05.935 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86232694169265}
03-15 20:42:12.296 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-71, mTimestampNanos=86239051067804}
03-15 20:42:12.436 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86239196387388}
03-15 20:42:12.712 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-98, mTimestampNanos=86239469748846}
03-15 20:42:17.346 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-87, mTimestampNanos=86244101039261}
03-15 20:42:17.616 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-87, mTimestampNanos=86244372349886}
03-15 20:42:22.388 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-42, mTimestampNanos=86249143803842}
03-15 20:42:22.657 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-42, mTimestampNanos=86249413593842}
03-15 20:42:27.374 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-50, mTimestampNanos=86254130413424}
03-15 20:42:27.421 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-96, mTimestampNanos=86254178738632}
03-15 20:42:27.642 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-38, mTimestampNanos=86254399760298}
03-15 20:42:27.693 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-96, mTimestampNanos=86254451050298}
03-15 20:42:32.251 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-39, mTimestampNanos=86259010351130}
03-15 20:42:32.309 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-93, mTimestampNanos=86259068604255}
03-15 20:42:32.527 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-40, mTimestampNanos=86259282907588}
03-15 20:42:37.525 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-37, mTimestampNanos=86264281754670}

既然这种扫描方式可以对扫描和过滤进行设置,那我们来试一下子吧~

在这里,我想仅仅扫描家里的体脂秤,所以,调用了setDeviceAddress(string)方法,把体脂秤的mac地址传递进去。

其实,这个时候就OK了,因为蓝牙mac地址是设备的唯一标识嘛,这样设备就一定会只扫描到我的目标设备了。

可是,我想把事情搞大一点,给过滤再加点限制,看是否还能扫描成功。

我又setServiceUuid()方法将体脂秤支持的service uuid传递进来。

        //过滤条件
        List<ScanFilter> bleScanFilters = new ArrayList<>();
        ScanFilter filter = new ScanFilter.Builder().setDeviceAddress("08:7C:BE:48:65:AD").setServiceUuid(ParcelUuid.fromString("0000fee7-0000-1000-8000-00805f9b34fb")).build();
        bleScanFilters.add(filter);

 再来对扫描设置进行一些定制:

设置扫描模式为低延迟模式,这种模式下可以更快的进行设备扫描,除此之外,还有均衡模式(SCAN_MODE_BALANCED)、低功耗模式(SCAN_MODE_LOW_POWER)。从字面意思,你应该也能猜出来,低延迟模式扫描设备最快,低功耗模式扫描设备最慢,均衡模式居中。

设置回调模式为全匹配(CALLBACK_TYPE_ALL_MATCHES),就是说,如果我们设置了过滤条件,则只上报过滤条件都完全匹配的设备,如果没有设置任何过滤条件,则上报扫描到的所有设备。

设置粘性匹配,就是在扫描到的设备满足一定信号强度时,才去跟过滤条件进行匹配,信号强度太弱,蓝牙固件直接丢弃,也不会去做匹配操作。

最后,我们将两个参数传递到startScan()方法中来。

        //扫描设置
        ScanSettings scanSetting = new ScanSettings.Builder().setScanMode(SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).setMatchMode(ScanSettings.MATCH_MODE_STICKY).build();
        mBluetoothLeScanner.startScan(bleScanFilters, scanSetting, mScanCallback);

看一下此时的扫描结果,我们的目标设备是可以正常扫描到,并且上报设备的粒度明显降低了。

03-15 21:12:14.335 16060-16060/com.atlas.devicefinder D/MainActivity: onClick,View = androidx.appcompat.widget.AppCompatButton{e98ee7a VFED..C.. ...P.... 0,288-426,432 #7f070043 app:id/bt_start_blescan2}
03-15 21:12:15.177 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-77, mTimestampNanos=88041917514200}
03-15 21:12:19.962 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-85, mTimestampNanos=88046719595240}
03-15 21:12:22.366 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-70, mTimestampNanos=88049124682114}
03-15 21:12:24.775 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-70, mTimestampNanos=88051533382946}
03-15 21:12:27.180 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-70, mTimestampNanos=88053936127529}

4.总结

利用上面提到了方式3 来进行设备扫描有什么好处呢?

在蓝牙固件中即进行设备匹配,可以大大减少蓝牙协议栈以及应用层的操作,降低内存占用、CPU占用。

可以根据需要进行扫描参数的设置,实现动态调整,进而实现快速扫描目标设备。

天不早了,该休息了~

本博客始终坚持理论与实践相结合,想尽最大努力将知识点讲解清楚,但不知道实际效果如何,

如果有任何建议,可以随时跟我沟通,谢谢。

如果想持续关注本博客内容,请扫描关注个人微信公众号,或者微信搜索:万物互联技术。

 
发布了35 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Atlas12345/article/details/104906179