Bluetooth permissions

To use Bluetooth features in your app, you must declare two permissions:

  • BLUETOOTH is necessary to perform any Bluetooth communication, such as requesting a connection, accepting a connection, and transferring data.
  • ACCESS_FINE_LOCATION is necessary because a Bluetooth scan can 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.

Since ACCESS_FINE_LOCATION is a dangerous permission, you must request this permission at runtime along with declaring it in your manifest.

Services running on Android 10 and higher cannot discover Bluetooth devices unless they have the ACCESS_BACKGROUND_LOCATION permission. For more information on this requirement, see Access location in the background.

The following code snippet shows how to check for the permission.

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    if (ContextCompat.checkSelfPermission(baseContext,
        Manifest.permission.ACCESS_BACKGROUND_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                    PERMISSION_CODE)
        }
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  if (ContextCompat.checkSelfPermission(baseContext,
      Manifest.permission.ACCESS_BACKGROUND_LOCATION)
      != PackageManager.PERMISSION_GRANTED) {
          ActivityCompat.requestPermissions(
              MyActivity.this,
              new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                  PERMISSION_CODE)
      }
}

On devices running Android 8.0 (API level 26) and higher, you can use the CompanionDeviceManager to perform a scan of nearby companion devices on behalf of your app without requiring the location permission. For more on this option, see Companion device pairing.

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. For example:

<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- If your app targets Android 9 or lower, you can declare
     ACCESS_COARSE_LOCATION instead. -->
<uses-permission android:name="android.permission.ACCESS_FINE_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 classic Bluetooth 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 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

private fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
...
// Check to see if the Bluetooth feature is available.
packageManager.takeIf { it.missingSystemFeature(PackageManager.FEATURE_BLUETOOTH) }?.also {
    Toast.makeText(this, R.string.bluetooth_not_supported, Toast.LENGTH_SHORT).show()
    finish()
}
// Check to see if the BLE feature is available.
packageManager.takeIf { it.missingSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) }?.also {
    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show()
    finish()
}

Java

// Use this check to determine whether Bluetooth is supported on the device.
// Then you can selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
    Toast.makeText(this, R.string.bluetooth_not_supported, Toast.LENGTH_SHORT).show();
    finish();
}
// Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
    finish();
}