You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API29下Jetpack Compose应用蓝牙权限自动授予异常问题

问题分析与解决方案

核心原因

API29(Android 10)中,BLUETOOTH、BLUETOOTH_SCAN、BLUETOOTH_CONNECT这类蓝牙相关权限属于正常权限,系统会在应用安装时自动授予,不需要用户手动确认。所以你调用requestPermissions时不会弹出授权对话框,直接返回权限已授予的结果,这和日志里显示的true以及直接收到onRequestPermissionsResult回调的表现完全吻合。

而定位权限(如ACCESS_FINE_LOCATION)属于危险权限,必须弹出授权对话框让用户确认,这就是两者表现不同的根本原因。

代码适配建议

1. 分版本处理权限逻辑

从API31(Android 12)开始,BLUETOOTH_SCAN、BLUETOOTH_CONNECT才被列为危险权限,需要动态申请并弹出对话框。如果你的应用需要兼容多版本,可按以下方式处理:

Button(onClick = {
    val bluetoothPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        arrayOf(
            Manifest.permission.BLUETOOTH_SCAN,
            Manifest.permission.BLUETOOTH_CONNECT
        )
    } else {
        arrayOf(
            Manifest.permission.BLUETOOTH
        )
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        ActivityCompat.requestPermissions(activity, bluetoothPermissions, 3)
    } else {
        // API31以下无需申请,直接使用权限即可
        Log.d("bluetooth permission", "权限已自动授予")
        // 执行蓝牙相关逻辑
    }
})

2. 优化权限回调判断

即使API29下会直接回调,也可以在onRequestPermissionsResult中增加结果校验,确保后续逻辑稳定:

@Deprecated("Deprecated in Java")
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 3) {
        val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
        Log.d("permission", "bluetooth 权限状态:$allGranted")
        // 这里处理权限授予后的业务逻辑
    }
}

总结

  • API29及以下版本,蓝牙权限为正常权限,安装即自动授予,不会触发授权对话框。
  • 若需适配API31+版本,必须针对BLUETOOTH_SCAN、BLUETOOTH_CONNECT做动态权限申请,此时才会弹出用户授权对话框。

内容的提问来源于stack exchange,提问作者Harvey Xie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 09:55:31