第2章 Android蓝牙权限适配清单

Android 蓝牙权限体系自 API 级别 23(Android 6.0)起逐步演变为运行时权限模型,并在 Android 12(API 31)中进行了重大拆分。本章梳理 BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION、BLUETOOTH_CONNECT 四种权限的适配要求,并给出完整的运行时请求流程。

2.1 权限清单与说明

权限名称用途最低 API是否需要运行时请求备注
BLUETOOTH发起蓝牙连接、扫描、配对等基础操作1否(Android 12 以下)
是(Android 12+ 用于传统场景)
Android 12 后若 targetSdkVersion≥31,必须声明 BLUETOOTH_CONNECT 替代
BLUETOOTH_ADMIN启用/禁用蓝牙、设置扫描模式1否(同上)同样在 Android 12+ 被 BLUETOOTH_SCAN 等拆解
ACCESS_FINE_LOCATION允许蓝牙扫描获取精确位置(用于 BLE 扫描)23是Android 10+ 需要;Android 12 后若仅使用 BLE,可改用 BLUETOOTH_SCAN(需配合)
BLUETOOTH_CONNECT发起蓝牙连接、配对、数据传输(Android 12+)31是替代 BLUETOOTH 的连接能力,无需位置权限
注意事项:若 targetSdkVersion 为 31 及以上,必须在 AndroidManifest.xml 中声明 BLUETOOTH_CONNECT 和 BLUETOOTH_SCAN(如需扫描),否则编译时会报权限缺失。

2.2 Android 12+ 新增 BLUETOOTH_CONNECT 权限

Android 12 将传统 BLUETOOTH 和 BLUETOOTH_ADMIN 拆分为更细粒度的运行时权限:

  • BLUETOOTH_CONNECT:用于连接已配对的蓝牙设备、传输数据。
  • BLUETOOTH_SCAN:用于扫描蓝牙设备(不涉及位置)。
  • BLUETOOTH_ADVERTISE:用于向外广播蓝牙信号。

对于仅需连接已配对设备的场景,只需 BLUETOOTH_CONNECT;若需扫描未配对设备,还需 BLUETOOTH_SCAN 和 ACCESS_FINE_LOCATION(Android 12 以下仍强制位置权限)。

2.3 运行时请求流程

以下步骤适用于 targetSdkVersion ≥ 31 的应用:

  1. 在 AndroidManifest.xml 中声明 BLUETOOTH_CONNECT(必要时加上 BLUETOOTH_SCAN 和 ACCESS_FINE_LOCATION)。
  2. 在代码中检查权限是否已授予(checkSelfPermission)。
  3. 若未授予,则调用 requestPermissions 发起运行时请求。
  4. 在 onRequestPermissionsResult 回调中处理结果。
  5. 权限授予后,才能执行蓝牙连接操作。

示例代码(Kotlin):

// 检查权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT)
    != PackageManager.PERMISSION_GRANTED) {
    // 请求权限
    ActivityCompat.requestPermissions(
        this,
        arrayOf(Manifest.permission.BLUETOOTH_CONNECT),
        REQUEST_BLUETOOTH_CONNECT
    )
} else {
    // 权限已授予,执行蓝牙操作
    connectBluetooth()
}

// 处理权限请求结果
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String>,
    grantResults: IntArray
) {
    when (requestCode) {
        REQUEST_BLUETOOTH_CONNECT -> {
            if (grantResults.isNotEmpty() &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                connectBluetooth()
            } else {
                // 处理拒绝逻辑(提示用户或降级)
            }
        }
    }
}
警告:在 Android 12 以下设备上,若 targetSdkVersion ≥ 31,系统可能会忽略 BLUETOOTH_CONNECT 权限(因为该权限不存在于旧版系统中),导致运行时崩溃。务必通过 Build.VERSION.SDK_INT 做版本判断,并在旧版使用 BLUETOOTH 权限。
建议:使用 androidx.activity.result.ActivityResultLauncher 代替旧式 requestPermissions,以获得更简洁的回调方式。
蓝牙权限适配流程图 1. 检查已授予权限 Android 12+? 是 请求 BLUETOOTH_CONNECT 否 请求 BLUETOOTH + 位置 用户授权结果 授权成功 执行蓝牙操作 授权失败 提示用户 / 降级 注:版本判断应在运行时进行,避免在旧设备上请求 BLUETOOTH_CONNECT
代码注意事项:在 Android 12 以下设备上,BLUETOOTH_CONNECT 权限在运行时 API 中不存在,直接请求会导致 Crash。必须通过 Build.VERSION.SDK_INT >= Build.VERSION_CODES.S 分支处理。

掌握上述权限适配清单及请求流程后,即可正确获取蓝牙连接权限。下一环节将基于此权限状态,建立安全的 Keystore 加密通道。