Flutter集成flutter_blue_plus扫描蓝牙设备ListView无结果求助
Flutter Blue Plus扫描蓝牙设备返回空列表问题
我正尝试在Flutter应用中集成flutter_blue_plus插件,但扫描可用蓝牙设备时始终得到空列表,无法显示可配对设备。设备为运行Android 13、One UI 5.1的安卓手机,已在设置中为应用授予所有权限(含位置权限),但ListView仍无法显示扫描到的设备。
控制器类代码
import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; class BluetoothController extends GetxController { FlutterBluePlus flutterBlue = FlutterBluePlus.instance; Future scanDevices() async { flutterBlue.startScan(timeout: const Duration(seconds: 5)); print("_________________________________________________________"); print(flutterBlue.scanResults); print("_________________________________________________________"); flutterBlue.stopScan(); } Stream<List<ScanResult>> get scanResults => flutterBlue.scanResults; }
扫描设备的Widget代码
Widget _buildPopupDialog(BuildContext context) { return new AlertDialog( title: const Text('List of available devices'), content: GetBuilder<BluetoothController>( init: BluetoothController(), builder: (controller) { return Container( height: MediaQuery.of(context).size.height/1.3, width: MediaQuery.of(context).size.width, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.max, children: [ GestureDetector( onTap: () { controller.scanDevices(); }, child: Container( height: MediaQuery.of(context).size.height / 20, width: MediaQuery.of(context).size.width / 3, decoration: BoxDecoration( color: Colors.blueAccent, border: Border.all( color: Colors.black, width: 1, ), borderRadius: BorderRadius.circular(10.0), //gradient: LinearGradient( //colors: [Colors.indigo, Colors.blueAccent]), boxShadow: const [ BoxShadow( color: Colors.white, blurRadius: 1.0, offset: Offset(1.0, 1.0)) ], ), child: Center( child: Text( "Scan Devices!!!", style: TextStyle( fontSize: MediaQuery.of(context).size.width/40, letterSpacing: 1, fontWeight: FontWeight.w400, color: Colors.black), ), ), ), ), SizedBox( height: 10, ), StreamBuilder<List<ScanResult>>( stream: controller.scanResults, builder: (context, snapshot){ if(snapshot.hasData) { return ListView.builder( shrinkWrap: true, itemCount: snapshot.data!.length, itemBuilder: (context,index){ final data = snapshot.data![index]; return Card( elevation: 2, child: ListTile( title: Text(data.device.name, selectionColor: Colors.black,), subtitle: Text(data.device.id.id), trailing: Text(data.rssi.toString()), ), ); }); } else { return const Center( child: Text("No devices found!!!"), ); } } ) ], ), ), ); }), actions: <Widget>[ new GestureDetector( onTap: () { Navigator.of(context).pop(); }, child: const Text('Close'), ), ], ); }
扫描时的日志输出
/ViewRootImpl@7b87c05[MainActivity](13581): ViewPostIme pointer 0 I/ViewRootImpl@7b87c05[MainActivity](13581): ViewPostIme pointer 1 I/flutter (13581): _________________________________________________________ I/flutter (13581): Instance of '_BroadcastStream<List<ScanResult>>' I/flutter (13581): _________________________________________________________ I/BluetoothAdapter(13581): STATE_ON I/BluetoothAdapter(13581): STATE_ON D/BluetoothLeScanner(13581): could not find callback wrapper I/BluetoothAdapter(13581): STATE_ON I/BluetoothAdapter(13581): STATE_ON I/BluetoothAdapter(13581): STATE_ON I/BluetoothAdapter(13581): STATE_ON D/BluetoothLeScanner(13581): Start Scan with callback D/BluetoothLeScanner(13581): onScannerRegistered() - status=0 scannerId=11 mScannerId=0 I/BluetoothAdapter(13581): STATE_ON I/BluetoothAdapter(13581): STATE_ON D/BluetoothLeScanner(13581): Stop Scan with callback
Android清单文件权限配置
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
问题原因及解决办法
1. 扫描逻辑错误:立即终止扫描
scanDevices方法中调用startScan后立刻执行stopScan,扫描还未完成就被终止,根本来不及收集设备数据。startScan是异步操作,带timeout参数时会自动在超时后停止扫描,无需手动提前终止。
修复后的控制器代码:
import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; class BluetoothController extends GetxController { FlutterBluePlus flutterBlue = FlutterBluePlus.instance; Future scanDevices() async { // 先停止可能存在的旧扫描 await flutterBlue.stopScan(); // 启动扫描,等待超时自动结束 await flutterBlue.startScan(timeout: const Duration(seconds: 5)); } Stream<List<ScanResult>> get scanResults => flutterBlue.scanResults; }
2. Android 13权限配置不完整
Android 13要求蓝牙扫描权限声明用途,需给BLUETOOTH_SCAN添加权限标志,同时确保权限申请逻辑正确。
修改后的权限配置:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- 若无需通过BLE获取位置,可移除以下两个权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
3. GetBuilder控制器实例不统一
每次GetBuilder构建时都会重新初始化BluetoothController,导致监听的流不是同一个实例的流。需全局初始化控制器:
修改后的Widget代码片段:
content: GetBuilder<BluetoothController>( init: Get.put(BluetoothController()), // 全局初始化一次 builder: (controller) { // 原有代码不变 }),
或者在页面初始化时提前注入控制器:
@override void initState() { super.initState(); Get.put(BluetoothController()); }
之后Widget中直接使用:
content: GetBuilder<BluetoothController>( builder: (controller) { // 原有代码不变 }),
4. 设备状态检查
确保手机蓝牙已开启,且待扫描的蓝牙设备处于可被发现模式(部分设备需手动开启该模式)。
内容的提问来源于stack exchange,提问作者shashank reddy
相关产品推荐
相关产品推荐

