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

相关推荐
江上清风山间明月2 小时前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能13 小时前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人13 小时前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen14 小时前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang1 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang1 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1231 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-1 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11191 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力2 天前
Flutter应用开发:对象存储管理图片
flutter