Android 11中蓝牙扫描权限处理异常:显示已授权但实际未授权
Android 11蓝牙扫描权限异常问题解析及修复
问题原因
Android 11(API 30)对蓝牙权限做了拆分,BLUETOOTH_SCAN属于普通权限,应用安装后系统会自动授予,不需要用户手动确认,所以你的代码中Permission.bluetoothScan.request()会直接返回isGranted,打印"Bluetooth scan permission granted"。但这个权限仅允许应用发起扫描请求,实际能成功扫描还需要两个前提:
- 设备蓝牙已开启
- 应用已获得
ACCESS_FINE_LOCATION危险权限
另外,普通权限不会显示在应用设置的权限页面中,只有危险权限(如位置、相机)才会被列出,这就是你在设置里看不到已授予权限的原因。
修复方案
1. 配置AndroidManifest.xml权限
在android/app/src/main/AndroidManifest.xml中添加必要权限:
<!-- 蓝牙扫描权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- 蓝牙连接权限(若需连接设备则添加) --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 11扫描蓝牙必需的位置权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 声明蓝牙硬件特性(可选,若应用依赖蓝牙可设为required="true") --> <uses-feature android:name="android.hardware.bluetooth" android:required="false" />
2. 修正权限请求代码
需要同时处理蓝牙状态检查和位置权限请求,确保扫描的前置条件都满足:
import 'package:permission_handler/permission_handler.dart'; import 'package:android_intent_plus/android_intent.dart'; Future setupBluetoothScan() async { // 检查蓝牙是否开启 final bluetoothStatus = await Permission.bluetooth.status; if (bluetoothStatus.isDenied) { // 引导用户跳转到蓝牙设置页面开启 final intent = AndroidIntent(action: 'android.settings.BLUETOOTH_SETTINGS'); await intent.launch(); return; } // 请求位置权限(Android 11+扫描蓝牙必需) final locationStatus = await Permission.accessFineLocation.request(); switch (locationStatus) { case PermissionStatus.granted: print("蓝牙扫描的所有前置条件已满足"); // 此处可执行蓝牙扫描逻辑 break; case PermissionStatus.denied: // 再次请求权限 await Permission.accessFineLocation.request(); break; case PermissionStatus.permanentlyDenied: // 引导用户跳转到应用设置开启权限 await openAppSettings(); break; default: print("位置权限被拒绝,无法进行蓝牙扫描"); } }
补充说明
- 若使用新版本
permission_handler插件,注意权限常量命名可能有调整,需对应Android官方权限字段。 - 仅需扫描蓝牙时可不用添加
BLUETOOTH_CONNECT权限,涉及设备连接操作则必须配置。
内容的提问来源于stack exchange,提问作者Om Prakash Tiwary




