我想设置一个ScanFilter来根据其广告数据扫描BLE设备:名称,服务UUID和其制造数据的第一个字符。问题是:当我使用ScanFilter时,没有回调,这意味着不会调用.onScanResult()。
设备名称正确,因为我已经通过在回调中找到设备进行了测试。当我不使用ScanFilter时,会出现回调,并且可以通过其名称找到该设备。并且它可以成功连接到设备。
这是我有问题的代码。您可以帮助指出问题吗?
我还有一个问题:如何为.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)
这是正确运行的代码。我可以用它来找到设备。但是我想通过制造数据过滤设备。扫描时是否需要设置过滤器?无论如何,这里是否可以通过其制造数据来过滤设备?
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();
}
}
答案 0 :(得分:0)
确实是设备发送的数据无效。格式基本上是以下顺序:
因此,如果我们拆分数据,则会得到:
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 。
因此,您将没有过滤器的运气。相反,您需要自己对其进行过滤。
答案 1 :(得分:0)
最终使它起作用!这是我的解决方案:
由于制造商数据无效(请参见上面@code的说明),我们不能直接使用Android提供的函数-scanRecord.getManufacturerSpecificData()。相反,我使用以下代码手动解析广告:
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
BluetoothDevice _device = result.getDevice();
ScanRecord scanRecord = result.getScanRecord();
byte[] byte_ScanRocord = scanRecord.getBytes();
int isLeft = byte_ScanRocord[9];//the 9th byte stores the information that can be used to filter the device
String byte_ScanRocord_str = Arrays.toString(byte_ScanRocord);
Log.i("onScanRecordAdv",byte_ScanRocord_str);
Log.i("onScanRecordisLeft",String.valueOf(isLeft));
if (_device != null && _device.getName() != null && _device.getName().matches(this.mDeviceName) && isLeft == 76 ) {
this.stopScan();
this.mDevice = _device;
Log.i("InsoleScanner", "mac address : " + this.mDevice.getAddress() + ", name : " + this.mDevice.getName());
this.mDeviceFoundLatch.countDown();
}
}