androidbluetoothandroid-permissions

Android 12 bluetooth permissions confusion


So in API 31 there are new Bluetooth permissions. I want to turn bluetooth on or off using this:

private void changeBluetoothState(boolean status) {
    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (status)
        mBluetoothAdapter.enable();
    else mBluetoothAdapter.disable();
}

and in manifest I already have this:

<uses-permission
    android:name="android.permission.WRITE_SETTINGS"
    tools:ignore="ProtectedPermissions" />

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

<uses-feature
    android:name="android.hardware.bluetooth"
    android:required="false" />

Android documentations says to add android:maxSdkVersion="30" to the above bluetooth permissions if targeting API 31 or higher. I also get an error in Android Studio that the enable() and disable() functions need "android.permission.BLUETOOTH_CONNECT".

  1. If adding android:maxSdkVersion="30" to tell the system to ignore the statement on higher APIs is optional rather than obligatory, does that mean that not adding it will allow the statement to work on higher APIs?

  2. If "android.permission.BLUETOOTH_CONNECT" is to allow my app to interact with other bluetooth devices then why is it needed to enable or disable the bluetooth adapter on the original device?

  3. If the BLUETOOTH_CONNECT permission needs to be requested at runtime what is the correct full way to do it? Meaning checking if it's already granted then requesting it if it's not. I have no Android 12 device so no way to test this code.


Solution

  • Targeting Android 12 my working solution is to declare the permissions in this way:

    <!--Before Android 12 (but still needed location, even if not requested)-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
    <!--From Android 12-->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    

    Like you said, BLUETOOTH_SCAN is not sufficient and you need BLUETOOTH_CONNECT (also if you decide, like me, to ask to the user to enable Bluetooth starting a new startActivityForResult with action BluetoothAdapter.ACTION_REQUEST_ENABLE)

    If the BLUETOOTH_CONNECT permission needs to be requested at runtime what is the correct full way to do it? Meaning checking if it's already granted then requesting it if it's not. I have no Android 12 device so no way to test this code.

    Yes, in the same way of asking location permission on Android < 12 (not need anymore) now you ask for both BLUETOOTH_SCAN and BLUETOOTH_CONNECT