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

Flutter使用flutter_blue扫描BLE设备无结果,请求代码排查帮助

Flutter BLE扫描应用问题排查

我是蓝牙开发新手,首次尝试开发扫描并连接附近蓝牙设备的Flutter应用,使用flutter_blue包编写了扫描代码,但真机运行时无法发现附近两台设备,同时出现权限相关日志,麻烦帮忙排查问题。

代码实现

class _MyHomePageState extends State<MyHomePage> {
  final FlutterBlue flutterBlue = FlutterBlue.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("BLE")),
      body: StreamBuilder<BluetoothState>(
        stream: flutterBlue.state,
        builder: (context, snapshot) {
          if (snapshot.data == BluetoothState.on) {
            return ScanForDevices(flutterBlue: flutterBlue);
          } else if (snapshot.hasError || snapshot.data == BluetoothState.unauthorized) {
            return Center(child: Text("Error"));
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

class _ScanForDevicesState extends State<ScanForDevices> {
  late List<ScanResult> result;

  @override
  void initState() {
    super.initState();
    widget.flutterBlue.startScan();
    // scanning();
  }

  scanning() {
    widget.flutterBlue.scanResults.listen((event) {
      for (ScanResult r in event) {
        result.add(r);
        print(r.device.id.toString() + "\n");
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder<List<ScanResult>>(
        stream: FlutterBlue.instance.scanResults,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView(
              children: snapshot.data!.map((e) => ListTile(
                leading: IconButton(
                  icon: Icon(Icons.present_to_all_sharp),
                  onPressed: () {
                    e.device.connect(timeout: Duration(seconds: 4));
                  },
                ),
                subtitle: Text("${e.device.name }\n ${e.device.id.id}"),
                title: Text(e.device.id.toString())
              )).toList(),
            );
          }
          if (snapshot.hasError) {
            return Text("Error");
          } else {
            return CircularProgressIndicator();
          }
        },
      ),
    );
  }
}

日志信息(翻译后)

权限被拒绝:ACCESS_COARSE_LOCATION
权限被拒绝:ACCESS_FINE_LOCATION
无法启动扫描:需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限


排查修复方案

1. 补全权限配置(核心问题)

从日志可以明确,扫描失败是因为缺少位置权限,Android平台要求BLE扫描必须获取位置权限:

  • 在android/app/src/main/AndroidManifest.xml中添加权限声明:
    <!-- 基础蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- 位置权限(BLE扫描必需) -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!-- Android 12+ 新增权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    
  • 动态请求权限:使用permission_handler包,在启动扫描前主动请求位置权限,示例代码:
    import 'package:permission_handler/permission_handler.dart';
    
    // 在initState中添加权限请求
    @override
    void initState() {
      super.initState();
      requestPermissions();
    }
    
    Future<void> requestPermissions() async {
      var status = await Permission.location.request();
      if (status.isGranted) {
        widget.flutterBlue.startScan(timeout: Duration(seconds: 10));
      } else {
        // 处理权限拒绝情况,提示用户开启权限
      }
    }
    

2. 修复代码逻辑问题

  • 初始化空列表:result变量未初始化,直接调用result.add(r)会触发空指针异常,在initState中添加:
    result = [];
    
  • 统一实例使用:StreamBuilder中使用FlutterBlue.instance.scanResults,建议改为传入的widget.flutterBlue.scanResults,保持实例一致性:
    stream: widget.flutterBlue.scanResults,
    
  • 添加扫描超时:避免持续扫描消耗电量,启动扫描时设置超时:
    widget.flutterBlue.startScan(timeout: Duration(seconds: 10));
    
  • 异常处理连接逻辑:连接设备时添加try-catch捕获异常:
    onPressed: () async {
      try {
        await e.device.connect(timeout: Duration(seconds: 4));
        // 连接成功后的业务逻辑
      } catch (e) {
        print("连接失败:$e");
        // 提示用户连接失败
      }
    },
    

3. 设备端检查

  • 确保测试设备蓝牙已正常开启,且目标BLE设备处于可广播/被发现状态;
  • 针对Android 12+设备,需确认已授予BLUETOOTH_SCAN和BLUETOOTH_CONNECT权限。

内容的提问来源于stack exchange,提问作者Sana'a Al-ahdal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 04:01:19