New Bluetooth permissions in Android 12

Android 12 introduces the BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT permissions, which let your app scan for nearby devices without needing to request the location permission. Your app must target Android 12 to declare these permissions.

If you want more control over the pairing and connecting experience, use the permissions described on this page.

Declare new permissions

If your app interacts with Bluetooth devices, it's strongly recommended that you do the following:

  1. If your app looks for Bluetooth devices, such as Bluetooth low energy (BLE) peripherals, add the BLUETOOTH_SCAN permission to your app's manifest.
  2. If your app makes the current device discoverable to other Bluetooth devices, add the BLUETOOTH_ADVERTISE permission to your app's manifest.
  3. If your app communicates with already-paired Bluetooth devices, add the BLUETOOTH_CONNECT permission to your app's manifest.
  4. For your legacy Bluetooth-related permission declarations, set android:maxSdkVersion to 30. This app compatibility step helps the system grant your app only the Bluetooth permissions that it needs when installed on devices that run Android 12.

The following code snippet demonstrates how to declare these new permissions in your app:

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

    <!-- Needed only if your app looks for Bluetooth devices.
         You must add an attribute to this permission, or declare the
         ACCESS_FINE_LOCATION permission, depending on the results when you
         check location usage in your app. -->
    <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" />
    ...
</manifest>
Figure 1. System permissions dialog, asking the user to grant an app permission to discover, advertise, and connect to nearby devices.

User-facing dialog

The BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT permissions are runtime permissions. Therefore, you must explicitly request user approval in your app before you can look for Bluetooth devices, make a device discoverable to other devices, or communicate with already-paired Bluetooth devices.

When your app requests at least one of the new Bluetooth permissions, the system prompts the user to allow your app to access Nearby devices, as shown in figure 1.

Consider how scan results are used

Consider carefully whether your app uses Bluetooth scan results to derive the device's location. Depending on your answer, complete the steps in one of the following sections.

App doesn't derive physical location

If your app doesn't 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:

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

  2. If location isn't otherwise needed for your app, remove the ACCESS_FINE_LOCATION permission from your app's manifest.

The following code snippet shows how to update your app's manifest file:

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

    <!-- 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" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- 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>

App derives physical location

If your app does derive physical location, you must continue to declare the ACCESS_FINE_LOCATION permission in your app's manifest, as shown in the following code snippet:

<manifest>
    <!-- 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.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Required if your app derives physical location from Bluetooth
         scan results. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    ...
</manifest>