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?
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
's requestPermissions()
method.
Here's what worked for me:
Add one of the following two lines to AndroidManifest.xml
, inside the root node:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
In your Activity, before attempting to connect to bluetooth, call Activity
's requestPermissions()
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
's onRequestPermissionsResult()
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 to requestPermissions()
is sufficient.