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

Flutter项目esc_pos_bluetooth无法识别热敏蓝牙打印机问题求助

问题描述

我使用的是esc_pos_bluetooth: ^0.4.1包,运行模板应用时功能正常,热敏蓝牙打印机可正常工作,但我将相同代码复制到自有项目后,打印机无法被识别。

相关代码

class PrinterScreen extends StatefulWidget {
  final Order order;
  PrinterScreen(this.order);
  @override
  _PrinterScreenState createState() => _PrinterScreenState();
}

class _PrinterScreenState extends State<PrinterScreen> {
  PrinterBluetoothManager printerManager = PrinterBluetoothManager();
  List<PrinterBluetooth> _devices = [];

  @override
  void initState() {
    super.initState();

    printerManager.scanResults.listen((devices) async {
      print('UI: Devices found ${devices.length}');
      setState(() {
        _devices = devices;
      });
    });
  }

  void _startScanDevices() {
    setState(() {
      _devices = [];
    });
    printerManager.startScan(Duration(seconds: 4));
  }

  void _stopScanDevices() {
    printerManager.stopScan();
  }

  void _testPrint(PrinterBluetooth printer) async {
    printerManager.selectPrinter(printer);

    const PaperSize paper = PaperSize.mm58;
    final profile = await CapabilityProfile.load();

    final PosPrintResult res =
        await printerManager.printTicket((await demoReceipt(paper, profile)));

    print(res.msg);
  }

  Future<List<int>> demoReceipt(
      PaperSize paper, CapabilityProfile profile) async {
    final Generator ticket = Generator(paper, profile);
    List<int> bytes = [];

    bytes += ticket.text('My name');
    bytes += ticket.text('is');
    bytes += ticket.text('Eric');
    bytes += ticket.text(DateTime.now().toString());
    bytes += ticket.text('Slide to the left');

    ticket.cut();
    return bytes;
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Printer page'),
      ),
      body: ListView.builder(
          itemCount: _devices.length,
          itemBuilder: (BuildContext context, int index) {
            return InkWell(
              onTap: () => _testPrint(_devices[index]),
              child: Column(
                children: <Widget>[
                  Container(
                    height: 60,
                    padding: EdgeInsets.only(left: 10),
                    alignment: Alignment.centerLeft,
                    child: Row(
                      children: <Widget>[
                        Icon(Icons.print),
                        SizedBox(width: 10),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: <Widget>[
                              Text(_devices[index].name ?? ''),
                              Text(_devices[index].address),
                              Text(
                                'Click to print a test receipt',
                                style: TextStyle(color: Colors.grey[700]),
                              ),
                            ],
                          ),
                        )
                      ],
                    ),
                  ),
                  Divider(),
                ],
              ),
            );
          }),
      floatingActionButton: StreamBuilder<bool>(
        stream: printerManager.isScanningStream,
        initialData: false,
        builder: (c, snapshot) {
          if (snapshot.data) {
            return FloatingActionButton(
              child: Icon(Icons.stop),
              onPressed: _stopScanDevices,
              backgroundColor: Colors.red,
            );
          } else {
            return FloatingActionButton(
              child: Icon(Icons.search),
              onPressed: _startScanDevices,
            );
          }
        },
      ),
    );
  }
}

依赖包配置

flutter_bluetooth_basic: ^0.1.7
esc_pos_bluetooth: ^0.4.1
esc_pos_utils: ^1.1.0

基础配置

  • Flutter版本:2.5.3
  • Android Manifest权限配置:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

运行效果对比

  • 模板应用运行效果:模板应用运行截图
  • 自有项目运行效果:自有项目运行截图

解决方案

按优先级依次排查:

  1. 补充运行时权限申请
    Android 6.0及以上系统要求位置权限、蓝牙相关权限必须动态申请,仅在Manifest声明不生效,模板项目默认集成了权限申请逻辑,自有项目缺失会导致扫描无结果。可使用permission_handler包实现,在调用扫描前先请求权限:
// 权限申请示例
Future<bool> requestBluetoothPermissions() async {
  if (Platform.isAndroid) {
    var locationStatus = await Permission.locationWhenInUse.request();
    var bluetoothStatus = await Permission.bluetooth.request();
    var bluetoothAdminStatus = await Permission.bluetoothAdmin.request();
    return locationStatus.isGranted && bluetoothStatus.isGranted && bluetoothAdminStatus.isGranted;
  }
  return true;
}
// 在_startScanDevices方法中先调用权限申请,权限通过后再执行扫描
  1. 检查minSdkVersion配置
    确认android/app/build.gradle中的minSdkVersion >= 19,这是esc_pos_bluetooth包要求的最低支持版本,低于该版本会导致扫描逻辑异常。

  2. 补充蓝牙状态判断
    当前代码未校验设备蓝牙是否开启,蓝牙未开启时扫描会直接返回空列表,建议在扫描前先判断蓝牙状态,未开启则引导用户打开蓝牙。

  3. 排查依赖冲突
    运行flutter pub deps检查自有项目是否存在其他蓝牙相关依赖,和当前使用的flutter_bluetooth_basic版本冲突,如有冲突可在pubspec.yaml中添加dependency_overrides固定版本:

dependency_overrides:
  flutter_bluetooth_basic: ^0.1.7
  1. 检查混淆配置
    如果自有项目开启了release打包混淆,需在android/app/proguard-rules.pro中添加蓝牙相关类的保留规则,避免扫描相关逻辑被混淆移除:
-keep class com.example.flutter_bluetooth_basic.** { *; }

内容的提问来源于stack exchange,提问作者Eric Melo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 12:15:07