Search code examples
androidbluetoothlocationandroid-permissions

Should I request for location permissions when using bluetooth for pre Android 12 devices when targeting Android 12 (targetSdkVersion 32)


My app scans and connects to BLE devices from a foreground service. I want to upgrade SDK and target Android 12 (targetSdkVersion 32) and support older versions of Android.

Android 12 introduced changes regarding bluetooth permissions.

Android documentation says:

Since Android 12: BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, and BLUETOOTH_SCAN permissions are runtime permissions.

  1. 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:

Add the android:usesPermissionFlags attribute to your BLUETOOTH_SCAN permission declaration, and set this attribute's value to neverForLocation.

  1. If location isn't otherwise needed for your app, remove the ACCESS_FINE_LOCATION permission from your app's manifest.
<manifest>
    <!-- Include "neverForLocation" only if you can strongly assert that
         your app never derives physical location from Bluetooth scan results. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                     android:usesPermissionFlags="neverForLocation" />

    <!-- Not needed if you can strongly assert that your app never derives
         physical location from Bluetooth scan results and doesn't need location
         access for any other purpose. -->
    <!--
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    -->
    ...
</manifest>

I understand that the app should not request for the location permissions when the app runs on Android 12. My questions are:

  1. What with older devices ? Should my app request for runtime location permissions when running on pre Android 12 ?
  2. What with ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION and ACCESS_BACKGROUND_LOCATION permissions presence in the Manifest ?
  3. What with using bluetooth in a service? The Android documentation also says that if an app uses bluetooth in service then the app should request for ACCESS_BACKGROUND_LOCATION. Should the app request for the background location access permission or not ? I am confused.

Solution

  • Ad 1. Should my app request for the runtime location permissions when running on pre Android 12 ?

    Yes. The app should request for the runtime location permissions when running on pre Android 12

    Ad 2. What with ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION and ACCESS_BACKGROUND_LOCATION permissions presence in the Manifest ?

    These entries should be present in the Manifest. Additionally mark them using android:maxSdkVersion. The manifest should resemble:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="package.com">
        <!-- https://developer.android.com/guide/topics/connectivity/bluetooth/permissions -->
        ...
        <!-- Request legacy Bluetooth permissions on older devices. -->
        <uses-permission android:name="android.permission.BLUETOOTH"
            android:maxSdkVersion="30"/>
        <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
            android:maxSdkVersion="30"/>
    
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
            android:maxSdkVersion="28"/>
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
            android:maxSdkVersion="30"/>
        <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
            android:maxSdkVersion="30"/>
    
        <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
        <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
        ...
    </manifest>
    

    Ad 3. Should the app request for the ACCESS_BACKGROUND_LOCATION permission when uses bluetooth from a foreground service ?

    Yes. The app should request for it.

    Depending on the Android version, the app should request for:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
       // `BLUETOOTH_SCAN` and `BLUETOOTH_CONNECT` on Android 12 and newer
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
       // `ACCESS_FINE_LOCATION` and `ACCESS_BACKGROUND_LOCATION` on Android 10..<12
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
       // `ACCESS_COARSE_LOCATION` and `ACCESS_FINE_LOCATION` on Android 7..<10
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       // `ACCESS_COARSE_LOCATION` on Android 6
    } else {
       // None for previous versions
    }