BluetoothLeScanner.startScan with Android 6.0 does not discover devices
Solution 1
if permissions granted, have a try: turn ON the GPS.
Solution 2
Is you app prompting for Location permission on startup? If it's not, handle the code somewhere else so that it is being prompted.
Also you can check this to test if your app is working fine:
Open Settings > Apps > YourApplication > Permissions and enable Location and then try to scan for results.
Location will be listed under permissions only if you have provided ACCESS_COARSE_LOCATION on manifest.
Solution 3
Using the solutions provided above works but the side effect is that you have to have location services turned on for something that doesn't need it. An ugly and unsatisfying work around is to specify the target version in your manifest to
android:targetSdkVersion="21"
It allows scanning on my Nexus 7 even though the installed version is 6.0.1. I do not know what the side effects are of targeting a lower version than the installed version but at least scanning works. Might be the only solution for GPS-less devices (if such devices exist).
Google should be crucified for this.
Related videos on Youtube
![Jacopo Tosi](https://lh3.googleusercontent.com/-A9dFe5zUyH8/AAAAAAAAAAI/AAAAAAAAAd4/SXXRN-LB7Sk/photo.jpg?sz=256)
Jacopo Tosi
Updated on July 09, 2022Comments
-
Jacopo Tosi almost 2 years
I'm trying to use the function BluatoothLeScanner.startScan instead of the deprecated one BluetoothAdapter.startLeScan. Yesterday I updated my Nexus 5 to Android 6.0 and since that moment my app does not work anymore. I firstly add the preferences required ACCESS_COARSE_LOCATION as found here, https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id. Then I added the permission as described here: https://developer.android.com/training/permissions/requesting.html. But at the end it seems not working, it does not send back the ble devices.
This is my code:
manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.stm.sensitronapp"> <uses-sdk android:maxSdkVersion="23"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>`
DeviceScanActivity
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) { } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, MY_PERMISSIONS_REQUEST_ACCESS_COARSE); } } // Device scan callback. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { mScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); mLeDeviceListAdapter.addDevice(result.getDevice()); mLeDeviceListAdapter.notifyDataSetChanged(); } }; } } } final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { mSwipeRefreshLayout.setRefreshing(true); mLeDeviceListAdapter.clear(); mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED) { mBluetoothLeScanner.startScan(mScanCallback); } }
EDIT: to solve this problem I only turned on the GPS. It is easy to do it programmatically in this way.
-
Matt Wolfe over 8 yearsI have the same issue. Have you found any workarounds? I'm thinking of trying the new scanning api but it's a pain to keep compatibility between both since they work so much differently.
-
Jacopo Tosi over 8 yearsYes, look here, there is the solution: Bluetooth Low Energy startScan on Android 6.0 does not find devices However, the solution is: add permissions in the manifest, add permissions at runTime in the activity with the ScanDevice, turn ON the GPS. Is incredible to think but my problem was the GPS off
-
Matt Wolfe over 8 yearsI just tested with GPS turned on and it worked (I was on a tablet which had it off).. This is crazy that we must have GPS turned on in order to scan for BLE devices, what if the device doesn't even have a GPS chip in it? A bug needs to get filed immediately. I would think the fitbit guys and others making BLE devices for the masses would have hit google with these questions already.
-
Lars Blumberg over 8 yearsWTF, enabling GPS on Android 6.0 makes the scanner finding BLE devices. Now I understand why the permission
ACCESS_COARSE_LOCATION
is required. Google, WTF?!? -
BjornW about 5 years4 years later and still the same problem with GPS...
-
J. Ouwehand over 2 yearsIn my case
disabling battery optimization
for the app solved the problem.
-
-
Jacopo Tosi over 8 yearsI added Location permissions, but it is not working. It starts the scanning but it does not reply anything in the callback.
-
4ntoine over 8 yearsi've added 'fine' and 'coarse' permissions but still no luck. discovery callback is not fired. Marshmallow on Nexus 9. i've checked Location is allowed in android settings for the app. I can see the device is found but callback is not fired. Also i can check it's fired on Lollipop. Any solution?
-
Piotr Wittchen over 8 yearsI can confirm that. After adding ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION to the Manifest AND enabling Location in the phone, BLE scan works. I've tested it on Nexus 6 with Android 6.0 and it works.
-
Mackovich over 8 yearsThat's the classic Bluetooth scan. OP is talking about LE scan.
-
Mackovich over 8 yearsI'm sorry if you got the wrong impression. I am just pointing that there is absolutely no relation between Bluetooth Classic Discovery and Bluetooth Low Energy Scan. Those two scans are completely different. The first scan will never return BLE devices unless there are dual mode and discoverable. And finally, you don't need location permission and enabled for Classic Bluetooth Discovery (just tried that today).
-
Usman khan over 8 yearsBut why so? I am only accessing Bluetooth? P.S: your solution does work though
-
qinmiao over 8 yearsAndroid 6.0 Changes:To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs.
-
Anticro over 7 yearsWould be nice, but in my case it is not an option to turn on GPS, in order to receive beacon advertisements. You simply can't find a working explanation, what GPS is used for, when the task is to receive bluetooth signals... ;-)
-
Brian Reinhold over 7 yearsBut the 'classic' search for devices in the standard settings options also scans for BTLE devices. So it discovers both classic and BTLE devices. The down side is that the only next step one can take is to pair with the device. Thus one cannot connect to BTLE devices that don't pair using this approach.
-
Brian Reinhold over 3 yearsOld, but ...The standard way to add the permissions is have the user give the app permission on a first time start up. It's a pain to implement.