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

Flutter Android插件请求蓝牙权限触发SecurityException异常问题

解决Android 12+启动蓝牙启用Intent的SecurityException问题

问题根源

Android 12(API 31)及以上版本中,BLUETOOTH_CONNECT属于危险权限,仅在AndroidManifest.xml中声明权限是不够的,必须在运行时主动向用户申请授权。你的代码直接启动BluetoothAdapter.ACTION_REQUEST_ENABLE Intent时,系统检测到App未获得该权限,因此抛出SecurityException。

解决方案

修改BluetoothPermissionActivity的逻辑,先检查并申请BLUETOOTH_CONNECT权限,获得授权后再启动蓝牙启用请求:

1. 修改Activity代码

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.bluetooth.BluetoothAdapter
import androidx.activity.result.contract.ActivityResultContracts
import android.content.pm.PackageManager

internal const val ACTION_PERMISSIONS_GRANTED = "BluetoothPermission.permissions_granted"
internal const val ACTION_PERMISSIONS_DENIED = "BluetoothPermission.permissions_denied"

class BluetoothPermissionActivity: AppCompatActivity() {

    // 权限申请回调
    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            launchBluetoothEnableIntent()
        } else {
            sendBroadcast(Intent(ACTION_PERMISSIONS_DENIED))
            finish()
        }
    }

    // 蓝牙启用请求回调
    private val bluetoothEnableLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            sendBroadcast(Intent(ACTION_PERMISSIONS_GRANTED))
        } else {
            sendBroadcast(Intent(ACTION_PERMISSIONS_DENIED))
        }
        finish()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 检查BLUETOOTH_CONNECT权限
        if (checkSelfPermission(android.Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
            launchBluetoothEnableIntent()
        } else {
            requestPermissionLauncher.launch(android.Manifest.permission.BLUETOOTH_CONNECT)
        }
    }

    private fun launchBluetoothEnableIntent() {
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        bluetoothEnableLauncher.launch(enableBtIntent)
    }
}

2. 补充说明

  • 若你的插件需要扫描蓝牙设备,Android 12+下BLUETOOTH_SCAN同样是危险权限,需按相同逻辑动态申请。
  • 权限申请或蓝牙启用操作完成后,务必调用finish()关闭当前Activity,避免残留后台页面。
  • 若用户永久拒绝权限,可在权限回调中通过shouldShowRequestPermissionRationale()判断,引导用户前往应用设置页面手动开启权限。

为什么之前的配置无效?

你的AndroidManifest.xml权限声明是正确的,但Android 12+对危险权限的管控更严格:

  • 危险权限必须通过ActivityResultContracts.RequestPermission()或RequestMultiplePermissions()在运行时申请
  • 未获得授权时,调用需要该权限的系统API或Intent会直接抛出SecurityException

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:05:12