部分Android设备中Flutter Blue无法扫描蓝牙设备问题求助
Android设备蓝牙扫描权限问题解决方案
问题根源
你的报错明确指向BLUETOOTH_SCAN权限缺失,这是因为Android 12(API 31)及以上版本重构了蓝牙权限体系,旧的BLUETOOTH、BLUETOOTH_ADMIN权限已被拆分,仅保留给Android 11及以下设备使用。
1. 更新AndroidManifest.xml权限配置
针对不同Android版本添加对应权限,确保覆盖全部设备:
<!-- Android 12+ 核心蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- 旧版本(Android 11及以下)兼容权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <!-- 位置权限(仅当扫描需要关联位置时添加,比如部分BLE设备依赖位置扫描) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" /> <!-- 后台扫描权限(如果应用需在后台执行扫描) --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" android:maxSdkVersion="31" />
- 若你的应用扫描不需要关联位置,保留
android:usesPermissionFlags="neverForLocation";若需要(比如扫描周边BLE设备),则移除该属性,并确保动态申请位置权限。
2. 动态权限申请适配不同Android版本
使用permission_handler时,需根据系统版本判断要申请的权限,避免统一申请无效权限:
import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; Future<bool> requestRequiredPermissions() async { if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 31) { // Android 12+ 申请蓝牙扫描和连接权限 final scanGranted = await Permission.bluetoothScan.request().isGranted; final connectGranted = await Permission.bluetoothConnect.request().isGranted; return scanGranted && connectGranted; } else { // Android 11及以下 申请蓝牙和位置权限 final bluetoothGranted = await Permission.bluetooth.request().isGranted; final locationGranted = await Permission.locationWhenInUse.request().isGranted; return bluetoothGranted && locationGranted; } } // iOS 权限处理(按需添加) return true; }
注意:调用蓝牙扫描前,务必先调用上述方法确认权限已全部授予,否则会抛出权限异常。
3. 升级或替换蓝牙插件
原flutter_blue插件已长期未维护,对Android 12+的权限适配存在缺陷。建议:
- 升级到
flutter_blue的最新稳定版(若仍有维护); - 替换为
flutter_blue_plus(flutter_blue的社区维护分支,完全兼容Android 12+权限体系)。
4. 额外排查点
- 蓝牙状态检查:扫描前确认设备蓝牙已开启,可通过插件提供的API(如
FlutterBlue.instance.isOn)判断,若未开启则调用FlutterBlue.instance.enable()请求用户开启; - 位置服务:部分定制化Android系统(如小米、华为)即使Android 12+已声明
neverForLocation,仍要求开启位置服务才能扫描蓝牙,可提示用户手动开启; - 后台权限:若应用需在后台扫描,除配置对应权限外,还需确保应用已获得后台运行权限(部分设备需用户手动在系统设置中开启)。
内容的提问来源于stack exchange,提问作者Guru Subramani
相关产品推荐
相关产品推荐

