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.
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.
Here is my problematic code. Can you help with indicating its problem?
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)); }
I got these errors:
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();
}
}