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

Android Studio中Kotlin请求蓝牙扫描/连接权限遭拒求解决方案

Kotlin中正确请求Android 12+蓝牙权限的实现方式

你的代码始终提示权限被拒,核心问题在于未在AndroidManifest.xml中正确声明权限,同时缺少对用户拒绝权限且勾选“不再询问”场景的处理。以下是完整的正确实现步骤:

1. 配置AndroidManifest.xml权限

必须在清单文件中声明所需蓝牙权限,同时兼容旧版本系统:

<manifest ...>
    <!-- Android 12以下版本的蓝牙权限(仅兼容用) -->
    <uses-permission android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" />

    <!-- Android 12+ 核心蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- 若无需通过蓝牙获取位置,添加此flag避免位置权限要求 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
        android:usesPermissionFlags="neverForLocation" />

    <!-- 声明设备蓝牙支持(可选,若App允许无蓝牙设备运行,添加required="false") -->
    <uses-feature android:name="android.hardware.bluetooth" android:required="true" />
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />

    <application ...>
        ...
    </application>
</manifest>

2. 修正Activity权限请求逻辑

添加权限合理性提示,以及处理用户拒绝权限且“不再询问”的场景,引导用户前往设置页开启权限:

class MainActivity : AppCompatActivity() {

    // 多权限请求处理
    private val requestMultiplePermissions =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
            permissions.entries.forEach { (permission, isGranted) ->
                Log.d("test", "$permission = $isGranted")
                if (!isGranted) {
                    when {
                        // 用户拒绝且勾选不再询问,引导去设置页
                        !shouldShowRequestPermissionRationale(permission) -> {
                            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                                data = Uri.fromParts("package", packageName, null)
                            }
                            startActivity(intent)
                            Toast.makeText(this, "请在设置中开启蓝牙权限", Toast.LENGTH_LONG).show()
                        }
                        // 用户拒绝但未勾选不再询问,提示权限重要性
                        else -> {
                            Toast.makeText(this, "${permission}权限被拒绝,部分功能无法使用", Toast.LENGTH_SHORT).show()
                        }
                    }
                }
            }
        }

    // Android 12以下启用蓝牙的请求处理
    private val requestEnableBluetooth =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == RESULT_OK) {
                Toast.makeText(this, "蓝牙已启用", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this, "蓝牙启用被拒绝", Toast.LENGTH_SHORT).show()
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val button = findViewById<Button>(R.id.button)

        button.setOnClickListener {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                // Android 12+ 请求蓝牙扫描与连接权限
                requestMultiplePermissions.launch(
                    arrayOf(
                        Manifest.permission.BLUETOOTH_SCAN,
                        Manifest.permission.BLUETOOTH_CONNECT
                    )
                )
            } else {
                // Android 11及以下,直接请求启用蓝牙(旧版本蓝牙权限安装时授予)
                val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                requestEnableBluetooth.launch(enableBtIntent)
            }
        }
    }
}

额外注意事项

  • 如果App需要通过蓝牙扫描获取位置(如蓝牙信标定位),不能添加neverForLocation flag,此时还需根据系统版本请求ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限。
  • 权限请求必须由用户交互触发(如按钮点击),不能在Activity启动时自动发起,否则系统可能直接拒绝请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:15:26