48

I'm developing an application with Bluetooth Low Energy using Nexus 5. It worked on Lollipop and now it is not working on Marshmallow. I set the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions in the manifest and on runTime in the Activity.

This is the list of ScanFilters:

mScanFilterTest = new ScanFilter.Builder().build();
mScanFilter = new ArrayList<ScanFilter>();
mScanFilter.add(mScanFilterTest);

These are the settings:

mScanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).setReportDelay(0)
                .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();

These are my callbacks:

 mBLEScan = new ScanCallback() {
     @Override
     public void onScanResult(int callbackType, ScanResult result) {
         super.onScanResult(callbackType, result);
         Log.i(TAG, "******************************************");
         Log.i(TAG, "The scan result " + result);
         Log.i(TAG, "------------------------------------------");
         }
     };

This is my call:

mBluetoothLeScanner.startScan(mScanFilter, mScanSettings, mBLEScan);

It starts the scan but does not find any device. Please help me!!!!

Jacopo Tosi
  • 752
  • 2
  • 7
  • 9

3 Answers3

72

I struggled with the same issue. To fix it you have to enable "Location" (GPS) in the settings of the phone as well as request location permission in the app at runtime. Both need to be done for scanning to work properly.

To request the location permission put the following in a dialog or the likes:

yourActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, yourPermissionRequestCode);

and implement:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){
    if(requestCode == yourPermissionRequestCode)
    {
        ... //Do something based on grantResults
    }
}

in yourActivity and handle whatever the user selects. You also need to do the following to turn on your device's location services:

Intent enableLocationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
yourActivity.startActivityForResult(enableLocationIntent, yourServiceRequestCode);

You can check if the user turned on the location services by implementing:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(requestCode == yourServiceRequestCode)
    {
        ...//Do whatever you need to
    }
}

in yourActivity. You can also manually turn on location (GPS) services by doing:

Enter phone settings -> Select "Location" -> Then turn it on

It should look like this in the Phone settings:

Location (GPS) services enabled in Phone Settings

Or like this in the quick-settings drop down:

Location (GPS) services enabled in drop down settings

Once the user has enabled the permission and started location services then you should start scanning. I've noticed that if you are already scanning while you enable the permission/turn on the location service it will still not put anything in your onScanResults

I'm not sure if this is a bug or a "feature" for iBeacons/Bluetooth advertising (NOTE: advertising as in selling products not the technical Bluetooth advertising) to allow companies to see your location and direct you to where they want.

Hope this fixes your problem!

EDIT I meant to add: you only need this for SCANNING. Once you are connected to the BLE device you can shut off the location service on your phone and you will still be connected to your devices. However, you cannot then discover or connect to any new devices and all advertising devices will drop from the onScanResults

V-PTR
  • 3,183
  • 3
  • 20
  • 21
  • I did it throught the settings and also with the code but it does not work. I add the permissions in the Manifest and also in the Activity at runTime. My manifest is: ` ` – Jacopo Tosi Oct 10 '15 at 00:56
  • 1
    Sorry for the delay, I updated my answer to be more complete. The big thing is you need to request the `ACCESS_COURSE_LOCATION` permission at run time **AND** turn on location services for the device. Once those are done you should start your scan and it should return something. Please let me know if this worked – V-PTR Oct 13 '15 at 14:24
  • I solved right now, the problem was you must turn on the gps during the scan. I don't know if you would say the same but this is the solution I found and it is working now. – Jacopo Tosi Oct 13 '15 at 14:31
  • Yeah, sorry for the confusion. The Location services I mention in the answer is the same as the GPS setting you mention. Sorry about that! – V-PTR Oct 13 '15 at 14:36
  • 4
    This works but it seems like a huge bug in the android system. Why must GPS be required in order to scan? My app uses GPS but only for customers who want that feature enabled and thus it will be confusing for customers who have it disabled in our app to get prompted to turn on GPS just so we can scan for BLE devices. – Matt Wolfe Oct 14 '15 at 15:58
  • 6
    @Matt Wolfe Yes, I agree, it seems like a huge bug. In fact, a bug report has been posted [here](https://code.google.com/p/android/issues/detail?id=189090&q=ble%20android%206.0&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars) asking what is going on with it. My hypothesis as to why it is this way is it allows advertising companies to use BLE GAP-only advertising devices (iBeacon devices and the like) to find where a customer is physically located a retail store (using triangulation) and be able to direct them to a product somewhere else in the store. But I could be completely wrong. – V-PTR Oct 14 '15 at 16:06
  • 4
    I actually only turned on GPS and everything worked without using requestPermissions(). I assumed after adding requestPermissions() the scan would work without GPS turned on, but I was wrong. What the hell Google?! – Lo-Tan Dec 02 '15 at 23:46
  • Minor typo: COURSE needs to be COARSE – Brian Reinhold Jan 21 '16 at 11:23
  • @BrianReinhold Thank you, it should be fixed now – V-PTR Jan 21 '16 at 12:52
  • 4
    @V-PTR *it seems like a huge bug* -- I read the Issue Tracker, but I concluded it not a bug. It is a feature which Google intends to for protecting users. Now, because of IoT, MAC addresses of bluetooth devices may be used for location identification. I guess architects of Google thought users should be noticed always when they are potentially in privacy risk. I think rather pre-Marshmallow devices have privacy protection problem about handling bluetooth devices information. – hata Mar 02 '16 at 19:00
  • thank you very much! location was not turned off in the quick-settings - wtf, already asking for location permission is confusing for the end user, but turning location on is even for me as developer extremely strange. I even didn't got an error message – Linard Arquint Sep 02 '16 at 15:40
  • @V-PTR you explicitly call out GPS, but I don’t see how GPS is specifically picked vs other location options, e.g., I see “GPS, Wi-Fi, and mobile networks”, “Wi-Fi and mobile networks”, and “GPS only”—should all work or only some? And if some, then is there anything special in making sure one of those is requested/set? – MrColes Jan 18 '17 at 16:24
  • 2
    @MrColes I don't believe it has to be GPS. I think any will work as long as the location service is on. I simply named GPS because that's what I personally associate location services with. I haven't explicitly tried the different location modes but I don't think it should make a difference. – V-PTR Jan 18 '17 at 17:35
  • @V-PTR one other nuance—in my testing, I see that Android 6.x only requires the permission, while Android 7.x requires both the permission and for location to be set to “on”. Do you or anyone else know if this is either a difference between 6.x & 7.x or a coincidence and maybe just different manufacturer’s phones being different? – MrColes Jan 19 '17 at 20:33
  • I've got scan devices but not shows me the same devices as if i go to Settings -> Bluetooth -> scan, i'm missing bluetooth devices – Billyjoker Jun 26 '17 at 08:01
  • 1
    To be clear, getting permission for location is not enough anymore? we need to force user to switch on location to scan BLE devices? am I wrong? – hasbi Feb 19 '18 at 12:06
2

Like @Jacopo Tosi say you must ask for location permissions. You can read here how to do it. And you also must turn on Location. i don't know why the did it. but it's the only way i managed to make it work.

Maor Hadad
  • 1,850
  • 21
  • 36
  • I turned on the location, it starts scanning but it doesn't reply anything in the callback – Jacopo Tosi Oct 11 '15 at 18:54
  • 1
    It doesn't really make it any better, but the reason behind it is that BLE beacons are often used as a sort of indoor GPS to track user location. So you have to have an awkward conversation with your user to request the permission and promise you will not try to track them, though they just granted that permission to a heart-rate monitor. – caller9 Jul 01 '16 at 22:19
0

In my case (HTC M9) I also had to go into Android Settings Menu under Bluetooth and manually scan for BT devices.

CodingYourLife
  • 7,172
  • 5
  • 55
  • 69