Flutter应用开发:蓝牙打印

背景

做的是物流相关的业务,蓝牙打印属于核心环节。主要涉及蓝牙连接打印设备,构建打印模板,构建打印队列,打印配置。

基础依赖

开始引入的基础依赖组件是bluetooth_print,发现业务场景上不能完全满足,下载到本地自己维护二次开发。涉及Android、IOS相关原生开发,从问题上来看,主要涉及权限、配置、打印方式、ios兼容等多方面处理。

经过多次修正引入业务项目,-_-||

yaml 复制代码
dependencies:
  bluetooth_print:
    path: ../packages/logistic-btprinter-plugin

沉浸式开发

蓝牙连接

回到设备连接上,怎么搜索到、怎么连接、怎么快捷连接?为啥会有这么多问题,因为业务员不关心连接,只想打印。直接参考手机上蓝牙连接的方式。

对于业务员来说,设备基本固定很少变更,一次连接后记忆,打开打印页面直接自动连接。连接过的设备信息记录在手机存储中,根据连接频率自动尝试连接使用最频繁的蓝牙设备。本来还想进一步区分蓝牙设备的种类,如下图,然后搜出来的设备信息根本无法区分种类,遂放弃。

具体在连接上还有很多细节,很容易遇到连接卡半天、频繁出错等问题,处理好这些才能提升用户体验。

  • 状态变化的约束
  • 连接失败的重试
  • 连接成功的记忆
  • 连接异常后的处理
js 复制代码
  // status ---> not_connect | connecting | connected | disconnecting
  Future<void> _connectDevice(BluetoothDeviceModel d, {bool? setPrefs}) async {
    await bluetoothPrint.stopScan();
    // 断开已有链接
    await _disconnectDevice();
    if (d.address != null) {
      if (d.status == 'connected') return;
      // 对接蓝牙设备
      setState(() {
        d.status = 'connecting';
      });

      G.print.jsonStr(d, '连接设备');

      await bluetoothPrint.connect(d);
      bluetoothPrint.state.listen((state) {
        switch (state) {
          case BluetoothPrint.CONNECTED:
            if (mounted) {
              setState(() {
                _connected = true;
                d.status = 'connected';
                _connectedDevice = d;
                // 移入存储
                if (setPrefs == true) {
                  _setDevicePrefs(_connectedDevice);
                }
              });
            }
            break;
          default:
            break;
        }
      }, onError: (object) {
        G.print.info('蓝牙连接-${object.toString()}', '连接状态Error');
      }, onDone: () {});

      int retryTimes = 20;
      while (retryTimes > 0) {
        retryTimes--;
        bool? isConnected = await bluetoothPrint.isConnected;
        if (isConnected == null || !isConnected) {
          sleep(Duration(milliseconds: 500));
          continue;
        } else {
          _connected = true;
          // 移入存储
          if (setPrefs == true) {
            _setDevicePrefs(_connectedDevice);
          }
          setState(() {
            d.status = 'connected';
            _connectedDevice = d;
          });
          G.toast('蓝牙设备连接成功');
          break;
        }
      }

      if (!_connected && mounted) {
        setState(() {
          d.status = 'not_connect';
        });
        G.toast('蓝牙设备连接失败');
      }
      if (!mounted) return;
    } else {
      setState(() {
        tips = '请选择打印设备';
        d.status = 'not_connect';
      });
      G.toast('请选择打印设备');
    }
  }

构建打印模板

打印模板完全是定制化的,不可能随便拿个邮政、顺风物流等打印模板就能用。打印模板对于代码来说就是一段字符串,不过遵循打印机CPCL编程,参考语法开发就行。涉及文本、位置、一维码、二维码、图片、线条等元素组合,还是需要研究一下的。

打印模板最好不要放置在项目代码中,放置到服务端存储成配置项。根据不同的业务场景可能随时可能替换,就比如当前应用对接一家业务公司就得定制化一套他们觉得OK的打印模板,其实他们就是想换LOGO而已。

构建打印队列

这个点也是很关键,因为一个订单下可能有很多运单,一个运单可能要打印两张,打印过程本身是异步过程。一个异步队列的必要条件集齐了。

维护队列的顺序、上限,因为是按需打印,需要同步维护打印状态,保证不遗漏一个单,不冗余一个单ヾ(◍°∇°◍)ノ゙。

js 复制代码
    // 判断设备连接情况
    if (_connectedDevice.status != 'connected') return;
    G.loading.show(context, text: '打印中...');
    if (_waybills.length > 0) {
      // 构建打印队列,维护顺序
      TaskQueueUtils taskQueueUtils = TaskQueueUtils.instance;
      taskQueueUtils.addListener(() {
        setState(() {
          _isPrinting = taskQueueUtils.isTaskRunning;
        });
      });

      _waybills.forEach((v) {
        taskQueueUtils.addTask(_printWaybill(v));
      });

      G.loading.hide(context);
    }

打印配置

打印配置分两个场景

打印模板相关配置

  • 单联打印、双联打印就需要在打印模板上配置
  • 打印模板的宽高适配打印纸也需在打印模板上设置

自定义配置

一次的打印上限控制队列上限即可

后记

Flutter在蓝牙打印上有多个第三方插件,结合自身业务场景慎重选择。打印细节上有优化空间,多测试多优化才能把功能做好。ヾ(◍°∇°◍)ノ゙

相关推荐
kirk_wang10 小时前
Flutter调用HarmonyOS NEXT原生相机拍摄&相册选择照片视频
flutter·华为·harmonyos
sunly_13 小时前
Flutter:carousel_slider 横向轮播图、垂直轮播公告栏实现
flutter
星释13 小时前
鸿蒙Flutter实战:17-无痛上架审核指南
flutter·华为·harmonyos
lichong95119 小时前
【Flutter&Dart】MVVM(Model-View-ViewModel)架构模式例子-http版本(30 /100)
android·flutter·http·架构·postman·win·smartapi
GY-9320 小时前
Flutter中PlatformView在鸿蒙中的使用
flutter·harmonyos
allanGold21 小时前
【Flutter】platform_view之AppKitView在哪个flutter版本添加的
flutter
sunly_1 天前
Flutter:进步器,数量加减简单使用
flutter
酱子姐1 天前
Flutter 架构原理
flutter
Callback_heaven1 天前
Flutter+vsCode 安装问题记录
ide·vscode·flutter
@福者2 天前
2025 最新flutter面试总结
flutter·面试·职场和发展