14

I have an app using bluetooth and connecting to devices, can'f find any devices using BluetoothAdapter.getDefaultAdapter().startDiscovery(); It worked fine just before discovery. Tried also other apps, it doesn't work in other apps as well. But the device I try to pair (Arduino bt-module) can be found in Android settings. Any idea what could I try? I implemented everything like described on http://developer.android.com/guide/topics/connectivity/bluetooth.html and it worked before the update.

mikugo
  • 155
  • 1
  • 2
  • 15

3 Answers3

31

Bluetooth Adapter has been change in Android 6.0

You need to set the permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission and need to use BluetoothLeScanner.startScan() method to start the scan.

Below is the description from change logs:

To provide users with greater data protection, in Android 6.0, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.

To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:

WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()

Note: When a device running Android 6.0 (API level 23) initiates a background Wi-Fi or Bluetooth scan, the operation is visible to external devices as originating from a randomized MAC address.

You can get more details from this link : http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html

Megha
  • 631
  • 7
  • 11
  • 3
    Thanks for the hint, the solution for me was to add the ACCESS_FINE_LOCATION permission and to request the permission at runtime. – mikugo Oct 10 '15 at 18:43
  • 1
    @mikugo Are you still using `BluetoothAdapter.getDefaultAdapter().startDiscovery();` for initiating the discovery? The changes mentions using the LEScanner instead for Marshmallow and wondering if you made the change to even scan for classic bluetooth devices. – jschlepp Jan 12 '16 at 03:43
  • @jschlepp Yes I'm using `BluetoothAdapter.getDefaultAdapter().startDiscovery();` it was only a small university project. But maybe the LEScanner can also discover classic devices because they use the same frequency. And it uses less power. – mikugo Jan 12 '16 at 10:34
  • I have those permissions set on the app, and I can discover devices, however, I can't connect with any of them. I think is something about permissions, cause it works on older versions (4.X and 5.X) – Diego Rivera May 09 '17 at 21:01
5

Just enable Location in Settings and it works well !!

Mark Ng
  • 59
  • 1
2

From API level 23, location access permission (ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION ) is also needed for bluetooth discovery.

https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id

And just adding permission into manifest file is not sufficient as the permission belongs to "dangerous" protection level. User consent is needed to request the permission at runtime.

Added permission into AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />

Request for ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION at run time:

private void accessLocationPermission() {
    int accessCoarseLocation = checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    int accessFineLocation   = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION);

    List<String> listRequestPermission = new ArrayList<String>();

    if (accessCoarseLocation != PackageManager.PERMISSION_GRANTED) {
        listRequestPermission.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    if (accessFineLocation != PackageManager.PERMISSION_GRANTED) {
        listRequestPermission.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
    }

    if (!listRequestPermission.isEmpty()) {
        String[] strRequestPermission = listRequestPermission.toArray(new String[listRequestPermission.size()]);
        requestPermissions(strRequestPermission, REQUEST_CODE_LOC);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_LOC:
            if (grantResults.length > 0) {
                for (int gr : grantResults) {
                    // Check if request is granted or not
                    if (gr != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                }

                //TODO - Add your code here to start Discovery

            }
            break;
        default:
            return;
    }
}

More details about permission: https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

mdrafiqulrabin
  • 1,657
  • 5
  • 28
  • 38