Android 12 New Bluetooth Permissions

24,945

Solution 1

This was a platform bug. Google fixed the bug in the new Android 12 Beta version.

Solution 2

100% working solution : no need any 3rd party plugin

manifest code:

   <!--BLUETOOTH PERMISSION-->
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- Needed only if your app looks for Bluetooth devices.
             If your app doesn't use Bluetooth scan results to derive physical
             location information, you can strongly assert that your app
             doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <!-- Needed only if your app makes the device discoverable to Bluetooth
      devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <!-- Needed only if your app communicates with already-paired Bluetooth
           devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <!--bibo01 : hardware option-->
    <uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>

Kotlin code:

 //check android12+
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                            requestMultiplePermissions.launch(arrayOf(
                                Manifest.permission.BLUETOOTH_SCAN,
                                Manifest.permission.BLUETOOTH_CONNECT))
                        }
                        else{
                            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                            requestBluetooth.launch(enableBtIntent)
                        }
....................................................

private var requestBluetooth = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    //granted
                }else{
                    //deny
                }
 }

private val requestMultiplePermissions =
                registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
                    permissions.entries.forEach {
                        Log.d("test006", "${it.key} = ${it.value}")
                    }
}

Read more: https://developer.android.com/guide/topics/connectivity/bluetooth/permissions

enter image description here

Solution 3

I just added to the manifest:

<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

and then I requested those permissions from Main Activity as any other. For requesting permission I am using library

implementation 'pub.devrel:easypermissions:3.0.0'

then you can just call this function

public static final String[] BLUETOOTH_PERMISSIONS_S = { Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT} ;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
     if (!EasyPermissions.hasPermissions(this, BLUETOOTH_PERMISSIONS_S)) {
                EasyPermissions.requestPermissions(this, message, yourRequestCode,BLUETOOTH_PERMISSIONS_S);
            }
        }

and override onRequestPermissionResult

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

UPDATE FOR JETPACK COMPOSE

If you are using jetpack compose you can handle it like this:

Create a list of your permissions inside of rememberMultiplePermissionState function

 rememberMultiplePermissionsState(
            permissions = listOf(
                Manifest.permission.BLUETOOTH_CONNECT,
                Manifest.permission.BLUETOOTH_SCAN
            )
        )

Then observe a lifecycle events and on resume launch permission request

    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(key1 = lifecycleOwner,
        effect = {
            val observer = LifecycleEventObserver { _, event ->
                if(event == Lifecycle.Event.ON_START) {
                    permissionsState.launchMultiplePermissionRequest()
                }
            }
            lifecycleOwner.lifecycle.addObserver(observer)

            onDispose {
                lifecycleOwner.lifecycle.removeObserver(observer)
            }
        })

Observe the permission state

permissionsState.permissions.forEach { permissionState ->
            when(permissionState.permission) {
                Manifest.permission.ACCESS_FINE_LOCATION -> {
                    when {
                        permissionState.hasPermission -> {}
                    }
                }
            }
        }
    }

Solution 4

This worked for me,

In the manifest, add the following permissions:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Then, before executing a Bluetooth function, check the permission:

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED) 
                {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) 
                    {
                        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 2);
                        return;
                    }
                }

For an example,

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 2);
                            return;
                        }
                    }
                    mBTSocket.connect();
Share:
24,945

Related videos on Youtube

Mustafa Kuloğlu
Author by

Mustafa Kuloğlu

Android Developer from Carly Connected Car. Interested in Linux, Linux kernel, and hardware. Curious about Artificial intelligence and machine learning.

Updated on March 07, 2022

Comments

  • Mustafa Kuloğlu
    Mustafa Kuloğlu over 2 years

    Bluetooth is the main dependency of our app. So, We already try to implement new Android 12 Bluetooth permissions. Our only resource is Android developers New Bluetooth permissions in Android 12. There is just saying add permissions

    "android.permission.BLUETOOTH_CONNECT"

    "android.permission.BLUETOOTH_SCAN"

    I add and I got runtime permissions for both and of course location(usual as pre 12)).
    There is no other change in my codebase. Should be? I don't know. So, the problem is my app can't find the BLE device. I couldn't find the reason.

    Do you have any suggestions or resources?

    • Dinkar Kumar
      Dinkar Kumar about 3 years
      not able to find BLE device on Android 12 or pre 12 as well?
    • or_dvir
      or_dvir about 3 years
      i am trying to add these permissions too but they dont exist in android studio... i only see the old ones (BLUETOOTH, BLUETOOTH_ADMIN, BLUETOOTH_ADMIN_PRIVILEGED). i set my targetSdkVersion to "S", my compileSdkVersion to "android-S", and my buildToolsVersion to "3.0.0-rc5". any idea?
    • Mustafa Kuloğlu
      Mustafa Kuloğlu about 3 years
      I can see. My settings like this: compileSdkVersion "android-S" buildToolsVersion "30.0.3" targetSdkVersion 31
  • Mustafa Kuloğlu
    Mustafa Kuloğlu about 3 years
    Thanks for your answer Barney and sorry for didn't mention it before but BLUETOOTH_ADMIN is already added. It is not working with that also.
  • RaJ
    RaJ over 2 years
    Working Fine. But Why Nearbyshare permission showing?
  • ocramot
    ocramot over 2 years
    Not totally working for me, I'm on Android 10. I don't see any popup asking for permissions, I immediately get to the part where the permissions are granted.