The following code works great on my Nexus 9 running Android 5.1.1 (Build LMY48M), but won't work on a Nexus 9 running Android 6.0 (Build MPA44l)
List<ScanFilter> filters = new ArrayList<ScanFilter>();
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)).build();
ScanFilter.Builder builder = new ScanFilter.Builder();
builder.setManufacturerData((int) 0x0118, new byte[]{(byte) 0xbe, (byte) 0xac}, new byte[]{(byte) 0xff, (byte)0xff});
ScanFilter scanFilter = builder.build();
filters.add(scanFilter);
mBluetoothLeScanner.startScan(filters, settings, new ScanCallback() {
...
});
On Android 5.x, the above code yields a callback when a manufacturer advertisement matching the scan filter is seen. (See example Logcat output below.) On the Nexus 9 with MPA44l, no callbacks are received. If you comment out the scan filter, callbacks are received successfully on the Nexus 9.
09-22 00:07:28.050 1748-1796/org.altbeacon.beaconreference D/BluetoothLeScanner﹕ onScanResult() - ScanResult{mDevice=00:07:80:03:89:8C, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={280=[-66, -84, 47, 35, 68, 84, -49, 109, 74, 15, -83, -14, -12, -111, 27, -87, -1, -90, 0, 1, 0, 1, -66, 0]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null], mRssi=-64, mTimestampNanos=61272522487278}
Has anybody seen ScanFilters work on Android M?
Add location permission along with BLE
Copy Paste this method to request and grant location permission
And then in onCreate check for permission
Hope it save your time.
I had a similar problem with an app connecting to bluetooth. Not LE ScanFilter, but it was a permissions issue just like the OP had.
Root cause is that starting with SDK 23, you need to prompt the user for permissions at runtime using
Activity
'srequestPermissions()
method.Here's what worked for me:
Add one of the following two lines to
AndroidManifest.xml
, inside the root node:In your Activity, before attempting to connect to bluetooth, call
Activity
'srequestPermissions()
method, which opens a system dialog to prompt the user for the permission. The permissions dialog opens in a different thread, so be sure to wait for the result before trying to connect to bluetooth.Override
Activity
'sonRequestPermissionsResult()
to handle the result. This method will really only need to do something if the user refused to grant the permission, to tell the user that the app can't do the bluetooth activity.This blog post has some example code that uses AlertDialogs to tell the user what's going on. It is a good starting point but has some shortcomings:
requestPermissions()
thread to finishrequestPermissions()
seems extraneous to me. A bare call torequestPermissions()
is sufficient.If your app targets Android Q, it's not enough with only coarse location, you need to use fine location, otherwise you will get this error:
See https://developer.android.com/preview/privacy/camera-connectivity#fine-location-telephony-wifi-bt for the official source.
The problem was not the scan filter, but that the scan filter was only being used when the app was in the background. (EDIT: This solution is out of date for Android 10 see below.) Starting with Android M, Bluetooth LE scanning in the background is blocked unless the app has one of the following two permissions:
The app I was testing did not request either of these permissions, so it did not work in the background (the only time the scan filter was active) on Android M. Adding the first one solved the problem.
I realized this was the problem because I saw the following line in Logcat:
See here for details: https://code.google.com/p/android-developer-preview/issues/detail?id=2964
EDIT: As of Android 10, coarse location is not enough -- you need fine location and a special background permission to detect BLE advertisements and beacons in the background. See here for details.
Place the following in your AndroidManifest.xml:
Then add code like follows to your Activity to dynamically request these permissions from the user: