要在您的应用程序中使用蓝牙功能,您必须 声明多个权限。您还应 指定您的应用程序是否需要支持 蓝牙经典或蓝牙低功耗 (BLE)。如果您的应用程序不需要蓝牙经典或 BLE,但仍然可以从这些技术中受益,则可以 在运行时检查可用性。
声明权限
您在应用程序中声明的权限集取决于应用程序的目标 SDK 版本。
目标 Android 12 或更高版本
注意: 在 Android 8.0 (API 级别 26) 和更高版本上,伴侣设备管理器 (CDM) 提供了一种比本节中描述的权限更简化的连接到伴侣设备的方法。CDM 系统代表您的应用程序提供配对 UI,并且不需要位置权限。
如果您希望对配对和连接体验有更多控制,请使用本节中描述的权限。
如果您的应用程序的目标是 Android 12 (API 级别 31) 或更高版本,请在应用程序的清单文件中声明以下权限
- 如果您的应用程序 查找蓝牙设备(例如 BLE 外设),请声明
BLUETOOTH_SCAN
权限。 - 如果您的应用程序 使当前设备可被其他蓝牙设备发现,请声明
BLUETOOTH_ADVERTISE
权限。 - 如果您的应用程序 与已配对的蓝牙设备通信,请声明
BLUETOOTH_CONNECT
权限。 - 对于您的传统蓝牙相关权限声明,请将
android:maxSdkVersion
设置为30
。此应用程序兼容性步骤有助于系统在安装在运行 Android 12 或更高版本的设备上的应用程序时,仅授予应用程序所需的蓝牙权限。 - 如果您的应用程序使用蓝牙扫描结果来推断物理位置,请声明
ACCESS_FINE_LOCATION
权限。否则,您可以 明确断言您的应用程序不会推断物理位置。
BLUETOOTH_ADVERTISE
、BLUETOOTH_CONNECT
和 BLUETOOTH_SCAN
权限是 运行时权限。因此,您必须在查找蓝牙设备、使设备可被其他设备发现或与已配对的蓝牙设备通信之前,在您的应用程序中明确 请求用户批准。当您的应用程序请求至少一项这些权限时,系统会提示用户允许您的应用程序访问**附近的设备**,如图 1 所示。
以下代码片段演示了如何在您的应用中声明与蓝牙相关的权限,前提是您的应用针对的是 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.
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>
强烈声明您的应用不推断物理位置
如果您的应用不使用蓝牙扫描结果推断物理位置,您可以做出强有力的声明,表明您的应用从不使用蓝牙权限推断物理位置。为此,请完成以下步骤。
将
android:usesPermissionFlags
属性添加到您的BLUETOOTH_SCAN
权限声明中,并将此属性的值设置为neverForLocation
。如果您的应用不需要位置,请从应用清单中删除
ACCESS_FINE_LOCATION
权限。
以下代码片段显示了如何更新应用的清单文件。
<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. -->
<strike><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /></strike>
...
</manifest>
面向 Android 11 或更低版本
如果您的应用针对的是 Android 11(API 级别 30)或更低版本,请在应用的清单文件中声明以下权限。
BLUETOOTH
是执行任何蓝牙经典或 BLE 通信所必需的,例如请求连接、接受连接和传输数据。ACCESS_FINE_LOCATION
是必需的,因为在 Android 11 及更低版本中,蓝牙扫描可能被用来收集有关用户位置的信息。
由于位置权限是 运行时权限,因此您必须在清单中声明它们的同时,在 运行时请求这些权限。
发现本地蓝牙设备
如果希望您的应用启动设备发现或操作蓝牙设置,则必须声明 BLUETOOTH_ADMIN
权限。大多数应用仅需要此权限来发现本地蓝牙设备。除非该应用是“电源管理器”,能够在用户请求时修改蓝牙设置,否则不要使用此权限授予的其他功能。在应用清单文件中声明该权限。例如
<manifest>
...
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
...
</manifest>
如果您的应用支持服务,并且可以在 Android 10(API 级别 29)或 Android 11 上运行,则还必须声明 ACCESS_BACKGROUND_LOCATION
权限才能发现蓝牙设备。有关此要求的更多信息,请参阅 在后台访问位置。
以下代码片段显示了如何声明 ACCESS_BACKGROUND_LOCATION
权限。
<manifest>
...
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
...
</manifest>
有关声明应用权限的更多信息,请参阅 <uses-permission>
参考。
指定蓝牙功能使用情况
如果蓝牙是应用的关键部分,则可以在清单文件中添加标志来指示此要求。 <uses-feature>
元素允许您指定应用使用的硬件类型以及它是否为必需的。
此示例显示了如何指示蓝牙经典对您的应用是必需的。
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
如果您的应用依赖于蓝牙低功耗,您可以使用以下方法。
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
如果声明功能对您的应用是必需的,那么 Google Play 商店会将您的应用隐藏在缺乏这些功能的设备的用户面前。因此,只有在没有该功能您的应用无法正常工作的情况下,才应将 required 属性设置为 true
。
在运行时检查功能可用性
为了使您的应用可用于不支持蓝牙经典或 BLE 的设备,您仍然应该在应用的清单文件中包含 <uses-feature>
元素,但将 required="false"
设置为。然后,在运行时,您可以使用 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);