在Bluetooth LE Con​​nection中使用ScanFilter时没有回调 [英] no callback when using ScanFilter in Bluetooth LE Connection

查看:397
本文介绍了在Bluetooth LE Con​​nection中使用ScanFilter时没有回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想设置一个ScanFilter来基于其广告数据扫描BLE设备:名称,服务UUID和其制造数据的第一个字符.问题是:当我使用ScanFilter时,没有回调,这意味着不会调用.onScanResult().

I would like to set a ScanFilter to scan a BLE device based on its advertisement data: name, services UUID, and the first character of its manufacture data. The problem is: when I use a ScanFilter, there is no callback, which means the .onScanResult() is not called.

该设备名称正确,因为我已经通过在回调中找到该设备进行了测试.当我不使用ScanFilter时,会出现回调,并且可以通过其名称找到该设备.并且它可以成功连接到设备.

The device name is correct because I have tested by finding the device in callback. When I don't use a ScanFilter, there is callback and the device can be found by its name. And it can successfully connect to the device.

  1. 这是我有问题的代码.您可以帮忙指出问题所在吗?

  1. Here is my problematic code. Can you help with indicating its problem?

另外,我还有一个问题:如何为.setManufacturerData()输入三个参数?

Also, I have another question: how to input the three parameters for .setManufacturerData()?

protected void scan(){

    List<ScanFilter> filters = new ArrayList<>();
    ScanFilter filterName = new ScanFilter.Builder().setDeviceName(this.mDeviceName).build();
    filters.add(filterName);
    //ScanFilter filterUUID = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("00001814-0000-1000-8000-00805F9B34FB")).build();
    //filters.add(filterUUID);
    //ScanFilter filterManu = new ScanFilter.Builder().setManufacturerData().build();
    //filters.add(filterManu);

    ScanSettings settings = (new Builder()).setScanMode(2).build();
    this.mBluetoothLeScanner.startScan(filters, settings, this);
    this.mScanning = true;
}

@Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        BluetoothDevice _device = result.getDevice();
                Log.i("onScanResult", " callback function is being called");

        // find device by name
        if (_device != null && _device.getName() != null && _device.getName().matches(this.mDeviceName) ) {
            this.stopScan();
            this.mDevice = _device;
            Log.i(TAG, "mac address : " + this.mDevice.getAddress() + ", name : " + this.mDevice.getName());
            this.mDeviceFoundLatch.countDown();
        }

        long m = mDeviceFoundLatch.getCount();
        Log.i("onResultscallbackLatch", String.valueOf(m));

    }

我遇到了这些错误:

E/ScanRecord: unable to parse scan record: [2, 1, 6, 3, 2, 20, 24, 2, -1, 82, 20, 9, 83, 116, 114, 105, 100, 97, 108, 121, 122, 101, 114, 32, 73, 78, 83, 73, 71, 72, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

E/BluetoothServiceJni: An exception was thrown by callback 'btgattc_scan_result_cb'.

E/BluetoothServiceJni: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.Map.get(java.lang.Object)' on a null object reference
        at android.bluetooth.le.ScanRecord.getServiceData(ScanRecord.java:121)
        at android.bluetooth.le.ScanFilter.matches(ScanFilter.java:305)
        at com.android.bluetooth.gatt.GattService.matchesFilters(GattService.java:659)
        at com.android.bluetooth.gatt.GattService.onScanResult(GattService.java:611)

这是正确运行的代码.我可以用它来找到设备.但是我想通过制造数据来过滤设备.扫描时是否需要设置过滤器?无论如何,这里是否可以通过其制造数据来过滤设备?

Here is the correctly running code. I can use it to find the device. But I would like to filter the device by its manufacture data. Do I have to set the filter when scanning? Is there anyway to filter the device by its manufacture data here?

protected void scan(){    
        ScanSettings settings = (new Builder()).setScanMode(2).build();
        this.mBluetoothLeScanner.startScan(null, settings, this);
        this.mScanning = true;
    }

    @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            BluetoothDevice _device = result.getDevice();
            if (_device != null && _device.getName() != null && _device.getName().matches(this.mDeviceName) ) {
                this.stopScan();
                this.mDevice = _device;
                this.mDeviceFoundLatch.countDown();
            }
        }

推荐答案

实际上是由设备发送的数据无效.格式基本上是以下顺序:

Indeed the data sent by the device is invalid. The format is basically a sequence of:

  • 数据长度(包括字段类型)
  • 字段类型
  • 数据

因此,如果我们拆分数据,则会得到:

So if we split the data, we get:

2: length 2 bytes
1: field type "flags"
6: data (flags)

3: length 3 bytes
2: field type "partial 16 bit UUID"
20, 24: data (UUID bytes 0x14 0x18, that will be converted into the full UUID 00001814-0000-1000-8000-00805F9B34FB)

2: length 2 bytes
-1 (or 0xff): field type "manufacturer data"
82: data (manufacturer data)

20: length 20 bytes
9: field type "local name complete"
83, 116, 114, 105, 100, 97, 108, 121, 122, 101, 114, 32, 73, 78, 83, 73, 71, 72, 84: data (local name, decoded as "Stridalyzer INSIGHT")
0, 0, ...: ignored data

不幸的是,制造商数据无效.它必须至少为3个字节(类型字段为4个字节),并以2个字节开头作为制造商ID.因此,此时,Android放弃了解析,并创建了一个完全没有数据的 ScanResult .

Unfortunately, the manufacturer data is invalid. It would need to be at least 3 bytes (4 with the type field) and start with 2 bytes for the manufacturer ID. So at this point, Android discard the parsing and creates a ScanResult with no data at all.

因此,您将没有过滤器的运气.相反,您需要自己对其进行过滤.

So you won't have any luck with filters. Instead, you will need to filter it yourself.

这篇关于在Bluetooth LE Con​​nection中使用ScanFilter时没有回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆