Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 12 New Bluetooth Permissions

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?

like image 660
Mustafa Kuloğlu Avatar asked May 27 '21 13:05

Mustafa Kuloğlu


People also ask

How do I check Bluetooth permissions on Android?

If your app looks for Bluetooth devices, such as BLE peripherals, declare the BLUETOOTH_SCAN permission. If your app makes the current device discoverable to other Bluetooth devices, declare the BLUETOOTH_ADVERTISE permission.

Why does Android BLE require location permissions?

Your app needs this permission because a Bluetooth scan can be used to gather information about the location of the user. This information may come from the user's own devices, as well as Bluetooth beacons in use at locations such as shops and transit facilities.”

What is the Bluetooth_admin permission?

If you want your app to initiate device discovery or manipulate Bluetooth settings, you must declare the BLUETOOTH_ADMIN permission in addition to the BLUETOOTH permission. Most apps need this permission solely for the ability to discover local Bluetooth devices.

Do Bluetooth apps need GPS permissions?

So even if an app just scans for Bluetooth devices and doesn’t utilize GPS or other tracking technologies, it still needed the same Location permission nonetheless. However, this led to unforeseen consequences when due to misunderstandings from users.

Does my app use Bluetooth permissions to derive physical location?

Needed only if your app uses Bluetooth scan results to derive physical location. --> ... If your app doesn't use Bluetooth scan results to derive physical location, you can make a strong assertion that your app never uses the Bluetooth permissions to derive physical location. To do so, complete the following steps:

Can You track Bluetooth devices on Android 12?

Basically, before Android 12, the ability to scan for nearby Bluetooth or Wi-Fi devices were tied to Android’s broader “location” permission. The reason this was the case makes sense: You can definitely track a device by inferring what Bluetooth devices or Wi-Fi networks are nearby or are currently connected.


Video Answer


5 Answers

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

like image 100
Hari Shankar S Avatar answered Oct 27 '22 05:10

Hari Shankar S


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" />

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

//--------------------------Java--------------------------
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;
                    }
                }

//--------------------------Kotlin--------------------------
if (ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED) 
               {
                   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) 
                   {
                       ActivityCompat.requestPermissions(this@MainActivity, arrayOf(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();
like image 7
HAZEEM JOONUS Avatar answered Oct 27 '22 06:10

HAZEEM JOONUS


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 -> {}
                    }
                }
            }
        }
    }
like image 7
Pesa Avatar answered Oct 27 '22 07:10

Pesa


If you want your app to initiate device discovery or manipulate Bluetooth settings, you must declare the BLUETOOTH_ADMIN permission in addition to the BLUETOOTH permission. Most apps need this permission solely for the ability to discover local Bluetooth devices. Don't use the other abilities granted by this permission unless the app is a "power manager" that modifies Bluetooth settings upon user request. Declare the Bluetooth permission(s) in your app manifest file

from developer android we see you have to add

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

in your manifest file but you did not add it to discover other devices i think this is the resource of your problem

like image 1
Barney Stinson Avatar answered Oct 27 '22 06:10

Barney Stinson


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

like image 1
Mustafa Kuloğlu Avatar answered Oct 23 '22 07:10

Mustafa Kuloğlu