Android 12 中的新蓝牙权限

Android 12 引入了 BLUETOOTH_SCANBLUETOOTH_ADVERTISEBLUETOOTH_CONNECT 权限,可让您的应用扫描附近的设备,而无需请求位置权限。您的应用必须以 Android 12 为目标平台,才能声明这些权限。

如果您想要更好地控制配对和连接体验,请使用本页介绍的权限。

声明新权限

如果您的应用与蓝牙设备互动,强烈建议您执行以下操作:

  1. 如果您的应用查找蓝牙设备(如蓝牙低功耗 (BLE) 外围设备),请向应用的清单中添加 BLUETOOTH_SCAN 权限。
  2. 如果您的应用使当前设备可被其他蓝牙设备检测到,请向应用的清单中添加 BLUETOOTH_ADVERTISE 权限。
  3. 如果您的应用与已配对的蓝牙设备通信,请向应用的清单中添加 BLUETOOTH_CONNECT 权限。
  4. 对于旧版蓝牙相关的权限声明,请将 android:maxSdkVersion 设为 30。此应用兼容性步骤有助于系统仅向您的应用授予在搭载 Android 12 的设备上安装时所需的蓝牙权限。

以下代码段演示了如何在您的应用中声明这些新权限:

<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>
图 1. 系统权限对话框,要求用户授予应用权限以发现、通告和连接到附近的设备。

面向用户的对话框

BLUETOOTH_SCANBLUETOOTH_ADVERTISEBLUETOOTH_CONNECT 权限是运行时权限。因此,您必须先在应用中明确请求用户批准,然后才能查找蓝牙设备、使某个设备可被其他设备检测到,或者与已配对的蓝牙设备通信。

当您的应用请求其中至少一项新的蓝牙权限时,系统会提示用户允许您的应用访问附近的设备,如图 1 所示。

考虑如何使用扫描结果

请仔细考虑您的应用是否使用蓝牙扫描结果来推导设备的位置。根据您的回答,完成以下某一部分中的步骤。

应用不推导物理位置

如果您的应用不推导物理位置,那么您可以坚定地断言您的应用绝不会使用蓝牙权限来推导物理位置。为此,请完成以下步骤:

  1. android:usesPermissionFlags 属性添加到 BLUETOOTH_SCAN 权限声明,并将此属性的值设为 neverForLocation

  2. 如果您的应用不需要位置信息,请从应用的清单中移除 ACCESS_FINE_LOCATION 权限。

以下代码段展示了如何更新应用的清单文件:

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

应用推导物理位置

如果您的应用确实推导物理位置,则您必须继续在应用的清单中声明 ACCESS_FINE_LOCATION 权限,如以下代码段所示:

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