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
相关产品推荐
相关产品推荐

