- Android 12 bluetooth permissions confusion
- What permissions would I need on Android if I want to use Bluetooth and Target SDK 31 but my minimum SDK is 23?
- 2 Answers 2
- New Bluetooth permissions in Android 12
- New permissions
- No location permission?
- Request user approval
- Conclusion
- How to set permissions for Android Bluetooth
- 3 Answers 3
Android 12 bluetooth permissions confusion
Targeting Android 12 my working solution is to declare the permissions in this way:
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.
To improve @AndreasGobs answer, below the code to test if the connection with a device is viable or not based on current available permissions. In the manifest I’ve set that the COARSE and FINE location permissions must be limited to max API 30. Tested on Android 6, 8.1, 11 and 12 devices. I hope this will be useful.
/** * - API < S * - Check ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions * - API < O * - Check has GPS * - Check GPS enabled * - API >= S * - Check BLUETOOTH_SCAN permission * - Check BLUETOOTH_CONNECT permission * - Check Bluetooth enabled */ private boolean canConnect() < Timber.d("canConnect called"); ListdeniedPermissions = new ArrayList<>(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) < if (!checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) deniedPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); if (!checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)) deniedPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); if(deniedPermissions.isEmpty())< if (!MmcDeviceCapabilities.hasLocationGps() //check if the device has GPS || Build.VERSION.SDK_INT < Build.VERSION_CODES.O || MmcDeviceCapabilities.isGpsEnabled())< //check if the GPS is enabled if(MmcDeviceCapabilities.bluetoothEnabled()) //check if bluetooth is enabled return true; else < requestEnableBluetooth(); //method to request enable bluetooth return false; >> else < Timber.d("Request enable GPS"); requestEnableGps(); //method to request enable GPS (improving devices scan) return false; >> else < Timber.d("Request GPS permissions"); requestRuntimePermissions( "Bluetooth GPS request", "GPS permissions request rationale", GPS_PERMISSIONS_CODE, deniedPermissions.toArray(new String[0])); return false; >> else < // Build.VERSION_CODES.S or later if(!checkPermission(Manifest.permission.BLUETOOTH_SCAN)) deniedPermissions.add(Manifest.permission.BLUETOOTH_SCAN); if(!checkPermission(Manifest.permission.BLUETOOTH_CONNECT)) deniedPermissions.add(Manifest.permission.BLUETOOTH_CONNECT); if(deniedPermissions.isEmpty()) if(MmcDeviceCapabilities.bluetoothEnabled()) //check if bluetooth is enabled return true; else < requestEnableBluetooth(); //method to request enable bluetooth return false; >else < Timber.d("Request bluetooth permissions"); requestRuntimePermissions( "Bluetooth permissions request", "Bluetooth permissions request rationale", CONNECT_PERMISSIONS_CODE, deniedPermissions.toArray(new String[0])); return false; >> > /** * This method checks if a runtime permission has been granted. * @param permission The permission to check. * @return TRUE
if the permission has been granted, FALSE
otherwise. */ @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean checkPermission(@NonNull String permission) < return ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED; >private void requestRuntimePermissions(@NonNull String title, @NonNull String description, int requestCode, @NonNull String. permissions) < if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[0])) < AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder .setTitle(title) .setMessage(description) .setCancelable(false) .setNegativeButton(android.R.string.no, (dialog, id) ->< //do nothing >) .setPositiveButton(android.R.string.ok, (dialog, id) -> ActivityCompat.requestPermissions(this, permissions, requestCode)); showDialog(builder); //method to show a dialog > else ActivityCompat.requestPermissions(this, permissions, requestCode); >
What permissions would I need on Android if I want to use Bluetooth and Target SDK 31 but my minimum SDK is 23?
Problem: I am wanting to make an application that requires Bluetooth functionality on Android and I’m not quite sure what permissions are required. I am going off of this documentation https://developer.android.com/guide/topics/connectivity/bluetooth/permissions, but the wording confuses me. In my app gradle file my targetSdk and compileSdk are both set to 31 which would be Android 12. My minSdk is set to 23 however which would be Android 6.0. At the very least I know my application will need to be able to scan for Bluetooth devices, connect, and communicate with devices. My app will not derive location from the Bluetooth scans. For a bare minimum my permissions needed would look like this:
This comes from the linked webpage under «Target Android 12 or Higher» but I’m wondering if I also need to abide by the «Target Android 11 or Lower» section as well since my minimum Android SDK is Android 6.0. So would I be good with following the Android 12 target instructions or the Android 11 or Lower target instructions?
2 Answers 2
You can use permissions for Bluetooth as follows for targetSdk set to 31 and minSdk to 23
Then while requesting permissions,
private String[] getRequiredPermissions() < int targetSdkVersion = getApplicationInfo().targetSdkVersion; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && targetSdkVersion >= Build.VERSION_CODES.S) < return new String[]; > else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && targetSdkVersion >= Build.VERSION_CODES.Q) < return new String[]; > else return new String[]; >
New Bluetooth permissions in Android 12
In this article, I will discuss the new Bluetooth permissions introduced in Android 12.
New permissions
For apps targeting Android 12 or higher, the following three new permissions are introduced:
- BLUETOOTH_CONNECT: required to connect to paired Bluetooth devices.
- BLUETOOTH_SCAN: equired to scan and pair nearby Bluetooth devices.
- BLUETOOTH_ADVERTISE: required to advertise to nearby Bluetooth devices.
For apps that also support older Android versions, we can declare the permissions like this:
. > android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> android:name="android.permission.BLUETOOTH_CONNECT" /> android:name="android.permission.BLUETOOTH_SCAN" /> android:name="android.permission.BLUETOOTH_ADVERTISE" /> .
No location permission?
Really? No location permission required now? Well, yes and no.
If the app uses Bluetooth to derive physical location, e.g. through BLE beacons, you still need to declare the ACCESS_FINE_LOCATION permission as before.
However, if the app does not derive physical locations, you can add the android:usesPermissionFlags=»neverForLocation» attribute to the BLUETOOTH_SCAN permission declaration:
. > android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> .
Request user approval
Unfortunately, when you run the app on Android 12 devices, you will get the SecurityException for missing the needed permissions. That’s because the new permissions are runtime permissions that must be approved by the user.
Assume the app doesn’t need to advertise, and doesn’t derive physical locations, we can request the permission like this:
class MainActivity : Activity() companion object private const val BLUETOOTH_PERMISSION_REQUEST_CODE = 9999 > override fun onCreate(savedInstanceState: Bundle?) super.onCreate(savedInstanceState) initializeBluetoothOrRequestPermission() ... > private fun initializeBluetoothOrRequestPermission() val requiredPermissions = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) listOf(Manifest.permission.ACCESS_FINE_LOCATION) > else listOf(Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN) > val missingPermissions = requiredPermissions.filter < permission -> checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED > if (missingPermissions.isEmpty()) initializeBluetooth() > else requestPermissions(missingPermissions.toTypedArray(), BLUETOOTH_PERMISSION_REQUEST_CODE) > > private fun initializeBluetooth() < ... > override fun onRequestPermissionsResult(requestCode: Int, permissions: Arrayout String>, grantResults: IntArray) when (requestCode) BLUETOOTH_PERMISSION_REQUEST_CODE -> if (grantResults.none < it != PackageManager.PERMISSION_GRANTED >) // all permissions are granted initializeBluetooth() > else // some permissions are not granted > > else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults) > > ... >
Conclusion
This is all you need to use the new Bluetooth permissions for Android 12 and above, and it’s really a great improvement for no longer requiring the location permission for scanning.
Let me know how if you have any questions and happy coding!
How to set permissions for Android Bluetooth
I’m new to Android development. I’m trying to get a simple HelloWorld app going on my (rooted) phone — and the app is trying to enable Bluetooth. I’ve set the Bluetooth permissions in my manifest is as follows, but I’m getting a Permission Denial exception when I try to run the application on my phone via Eclipse:
3 Answers 3
The answer about what to include in your manifest.xml for bluetooth activity includes
The first three are of greater priority and as I’m sure you’re aware there are different cases when each dependency may be required. Hope it helps with your setup!
I’m not quite sure what the problem was here.
All I can say is that I reinstalled Eclipse and its plugins and now everything is working fine. Thanks for your help Mayra — I’ll up-mark your answer because of your helpful and friendly approach.
Next time try to do «everything» logical and then reinstall, therefore your computer techniques will strengthen.
The element types in the manifest are ordered. I think the uses-permission needs to be first under the tag.
Thanks for the quick response Mayra. I’ve tried moving the uses-permission tag around in the file and it doesn’t seem to fix the problem — and the example manifest files I’ve seen often seem to include the uses-permission tags at the bottom of the file — so I don’t think that the location of the tag is critical.
Ok, I think you are right. I had a problem with permissions before that I thought was solved by order, but I see other places in the documentation where things are out of order. What is the exact error message that you are seeing?
Down voted, because in SO, we vote-up for quality of answer. Unfortunately, in spite of best intentions, the answer is incorrect.