To use Bluetooth features in your app, you must declare several permissions. You should also specify whether your app requires support for Bluetooth classic or Bluetooth Low Energy (BLE). If your app doesn't require Bluetooth classic or BLE but can still benefit from these technologies, you can check for availability at runtime.
Declare permissions
The set of permissions that you declare in your app depends on your app's target SDK version.
Target Android 12 or higher
Note: On Android 8.0 (API level 26) and higher, the Companion Device Manager (CDM) provides a more streamlined method of connecting to companion devices, compared to the permissions described in this section. The CDM system provides a pairing UI on behalf of your app and doesn't require location permissions.
If you want more control over the pairing and connecting experience, use the permissions described in this section.
If your app targets Android 12 (API level 31) or higher, declare the following permissions in your app's manifest file:
- 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. - If your app communicates with already-paired Bluetooth
devices, declare the
BLUETOOTH_CONNECT
permission. - 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 or higher. - If your app uses Bluetooth scan results to derive physical location, declare
the
ACCESS_FINE_LOCATION
permission. Otherwise, you can strongly assert that your app doesn't derive physical location and setandroid:maxSdkVersion
to 30 for theACCESS_FINE_LOCATION
permission.
The BLUETOOTH_ADVERTISE
, BLUETOOTH_CONNECT
, and BLUETOOTH_SCAN
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
these permissions, the system prompts the user to allow your app to access
Nearby devices, as shown in figure 1.
The following code snippet demonstrates how to declare Bluetooth-related permissions in your app if it targets Android 12 or higher:
<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.
If your app doesn't use Bluetooth scan results to derive physical
location information, you can
<a href="#assert-never-for-location">strongly assert that your app
doesn't derive physical location</a>. -->
<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" />
<!-- Needed only if your app uses Bluetooth scan results to derive
physical location. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
</manifest>
Strongly assert that your app doesn't 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:
Add the
android:usesPermissionFlags
attribute to yourBLUETOOTH_SCAN
permission declaration, and set this attribute's value toneverForLocation
.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>
<!-- 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" />
<!-- Set maxSdkVersion to 30 if you can strongly assert that, on
Android 12 and higher, 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"
android:maxSdkVersion="30" />
...
</manifest>
Target Android 11 or lower
If your app targets Android 11 (API level 30) or lower, declare the following permissions in your app's manifest file:
BLUETOOTH
is necessary to perform any Bluetooth classic or BLE communication, such as requesting a connection, accepting a connection, and transferring data.ACCESS_FINE_LOCATION
is necessary because, on Android 11 and lower, a Bluetooth scan could potentially be used to gather information about the location of the user.
Because location permissions are runtime permissions, you must request these permissions at runtime along with declaring them in your manifest.
Discover local Bluetooth devices
If you want your app to initiate device discovery or manipulate Bluetooth
settings, you must declare the
BLUETOOTH_ADMIN
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 permission in your app manifest file. For
example:
<manifest>
...
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
...
</manifest>
If your app supports a service and can run on Android 10 (API level 29) or
Android 11, you must also declare the
ACCESS_BACKGROUND_LOCATION
permission to discover Bluetooth devices. For more information on this
requirement, see Access location in the
background.
The following code snippet shows how to declare the ACCESS_BACKGROUND_LOCATION
permission:
<manifest>
...
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
...
</manifest>
See the <uses-permission>
reference for more information about declaring app permissions.
Specify Bluetooth feature usage
If Bluetooth is a critical piece of your app, you can add flags to your manifest
file indicating this requirement. The
<uses-feature>
element allows
you to specify the type of hardware your app uses and whether or not it is
required.
This example shows how to indicate that Bluetooth classic is required for your app.
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
If your app relies on Bluetooth Low Energy, you can use the following:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
If you say the feature is required for your app, then the Google Play store will
hide your app from users on devices lacking those features. For this reason, you
should only set the required attribute to true
if your app can't work without
the feature.
Check feature availability at runtime
To make your app available to devices that don't support Bluetooth classic or
BLE, you should still include the <uses-feature>
element in your app's
manifest, but set required="false"
. Then, at run-time, you can determine
feature availability by using
PackageManager.hasSystemFeature()
:
Kotlin
// Check to see if the Bluetooth classic feature is available. val bluetoothAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) // Check to see if the BLE feature is available. val bluetoothLEAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
Java
// Use this check to determine whether Bluetooth classic is supported on the device. // Then you can selectively disable BLE-related features. boolean bluetoothAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); // Use this check to determine whether BLE is supported on the device. Then // you can selectively disable BLE-related features. boolean bluetoothLEAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);