Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 6 bluetooth

I upgraded to Android 6 and my applications who use Bluetooth doesn't work with this new API version. It's the same problem with application on Play Store: Bluetooth spp tools pro (good application to view if bluetooth works) which doesn't discovery of devices.

The problem seems to be in Bluetooth discovery:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery()
Log.i("BLUETOOTH", String.valueOf(mBluetoothAdapter.isDiscovering())); // Return false

My applications work well with Android 4/5 and I followed : http://developer.android.com/guide/topics/connectivity/bluetooth.html

like image 628
eldina Avatar asked Oct 15 '15 07:10

eldina


2 Answers

Staring with Android 6.0 it is not enough to include permissions on manifest. You have to ask the user explicitly about each permission that is considered "dangerous". BluetoothDevice.ACTION_FOUND requires BLUETOOTH and ACCESS_COARSE_LOCATION permissions http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND

The ACCESS_COARSE_LOCATION http://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION is a "dangerous" permission and therefore you have to ask for it using requestPermission before doing actual discovery.

  public void doDiscovery() {
    int hasPermission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION);
    if (hasPermission == PackageManager.PERMISSION_GRANTED) {
        continueDoDiscovery();
        return;
    }

    ActivityCompat.requestPermissions(MainActivity.this,
            new String[]{
                    android.Manifest.permission.ACCESS_COARSE_LOCATION},
            REQUEST_COARSE_LOCATION_PERMISSIONS);
}

then on you will get the user answer on onRequestPermissionsResult

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
       case REQUEST_COARSE_LOCATION_PERMISSIONS: {
            if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                continueDoDiscovery();
            } else {
                Toast.makeText(this,
                        getResources().getString(R.string.permission_failure),
                        Toast.LENGTH_LONG).show();
                cancelOperation();
            }
            return;
        }
    }
}

To work with previous versions of android you should use compatibility libraries and make the calls using ActivityCompat

like image 136
Luci Avatar answered Sep 27 '22 22:09

Luci


I've spent some time investigating the problem.
Created bug report on Android bug tracker here
The problem is that system does not forward BluetoothDevice.ACTION_FOUND intents to the registered BroadcastReceiver. Logcat shows lines like this:

10-16 07:34:09.147      786-802/? W/BroadcastQueue﹕ Permission Denial: receiving Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } to ProcessRecord{5ce2d92 21736:com.example.mvl.bluetoothtest/u0a74} (pid=21736, uid=10074) requires android.permission.ACCESS_COARSE_LOCATION due to sender com.android.bluetooth (uid 1002)    

Which themes for me that the application needs android.permission.ACCESS_COARSE_LOCATION permission to receive this intents. i personaly don't understand why I need that permission to get the Bluetooth devices around.
So if you add this permission to you Manifest, then it should work with one more precondition - You have to set target SDK and compile with SDK not higher, then 22.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
like image 27
Vladyslav Matviienko Avatar answered Sep 27 '22 20:09

Vladyslav Matviienko