12 KiB
12 KiB
Printer 插件使用指南
本文档介绍 Flutter Printer 插件的安装、配置和使用方法。该插件封装了 Android
autoreplyprintSDK,提供了串口/USB 端口管理和票据打印功能。
目录
安装
1. 添加依赖
在 pubspec.yaml 中添加本地依赖:
dependencies:
printer:
path: ../printer # 根据实际路径调整
2. 配置 Android
将 docs/autoreplyprint.aar 文件放置到 Android 项目的 app/libs/ 目录下:
your_flutter_app/
└── android/
└── app/
└── libs/
└── autoreplyprint.aar
在 android/app/build.gradle 中确保 libs 目录被引用:
dependencies {
implementation files('libs/autoreplyprint.aar')
// ... 其他依赖
}
快速开始
基本打印流程
一个完整的打印流程包含三个步骤:打开端口 → 打印内容 → 关闭端口。
import 'package:printer/printer.dart';
final printer = Printer();
// 1. 打开端口
final handle = await printer.openComPort(
portName: '/dev/ttyS0',
baudRate: 115200,
);
// 2. 设置编码并打印文本
await printer.setMultiByteMode(handle);
await printer.setMultiByteEncoding(handle, MultiByteEncoding.utf8);
await printer.setAlignment(handle, PrinterAlignment.center);
await printer.printText(handle, 'Hello 中文\n');
await printer.feedLine(handle, 3);
// 3. 关闭端口
await printer.closePort(handle);
端口管理
枚举端口
// 枚举串口
final comPorts = await printer.enumComPorts();
print('可用串口: $comPorts');
// 枚举USB端口
final usbPorts = await printer.enumUsbPorts();
print('可用USB口: $usbPorts');
打开串口 (COM Port)
final handle = await printer.openComPort(
portName: '/dev/ttyS0', // 端口名称(必填)
baudRate: 115200, // 波特率(必填),需与打印机保持一致
dataBits: 8, // 数据位,默认8
parity: SerialParity.none, // 校验位,默认无校验
stopBits: SerialStopBits.one, // 停止位,默认1位
flowControl: SerialFlowControl.none, // 流控制,默认无
autoReplyMode: true, // 是否开启自动回传模式
);
参数说明:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
portName |
String |
是 | - | 端口名称,如 /dev/ttyS0 或 COM1 |
baudRate |
int |
是 | - | 波特率,如 9600, 19200, 38400, 57600, 115200 |
dataBits |
int |
否 | 8 |
数据位,范围 [4, 8] |
parity |
SerialParity |
否 | none |
校验位:none, odd, even, mark, space |
stopBits |
SerialStopBits |
否 | one |
停止位:one, onePointFive, two |
flowControl |
SerialFlowControl |
否 | none |
流控制:none, xonXoff, rtsCts, dtrDsr |
autoReplyMode |
bool |
否 | true |
是否开启自动回传模式 |
打开 USB 端口
final handle = await printer.openUsbPort(
portName: 'USB001', // 端口名称(必填),可不指定以自动查找
autoReplyMode: true, // 是否开启自动回传模式
);
检查端口状态
final isOpen = await printer.isPortOpened(handle);
if (isOpen) {
print('端口已打开');
}
关闭端口
final success = await printer.closePort(handle);
使用安全句柄 (推荐)
使用 PrinterPortHandle 可以更安全地管理端口资源,避免资源泄漏:
// 打开带句柄的串口
final portHandle = await printer.openComPortWithHandle(
portName: '/dev/ttyS0',
baudRate: 115200,
);
try {
// 执行打印操作
await printer.printText(portHandle.handle, 'Hello\n');
} finally {
// 确保端口被关闭
await portHandle.close();
}
同样支持 USB 端口:
final portHandle = await printer.openUsbPortWithHandle(
portName: 'USB001',
);
票据打印
打印文本
在打印文本之前,需要先设置多字节编码模式:
// 设置多字节模式
await printer.setMultiByteMode(handle);
// 设置编码为 UTF-8(支持中文等多语言字符)
await printer.setMultiByteEncoding(handle, MultiByteEncoding.utf8);
// 打印文本
await printer.printText(handle, 'Hello 中文\n');
支持的编码类型 (MultiByteEncoding):
| 编码 | 值 | 说明 |
|---|---|---|
gbk |
0 |
GBK 编码(简体中文) |
utf8 |
1 |
UTF-8 编码(Unicode,推荐) |
big5 |
3 |
BIG5 编码(繁体中文) |
shiftJis |
4 |
Shift-JIS 编码(日文) |
eucKr |
5 |
EUC-KR 编码(韩文) |
设置文本对齐
// 左对齐
await printer.setAlignment(handle, PrinterAlignment.left);
// 居中对齐
await printer.setAlignment(handle, PrinterAlignment.center);
// 右对齐
await printer.setAlignment(handle, PrinterAlignment.right);
设置文本缩放
宽度和高度缩放值范围为 1 到 8:
await printer.setTextScale(
handle,
widthScale: 2, // 宽度放大2倍
heightScale: 2, // 高度放大2倍
);
await printer.printText(handle, 'Large Text\n');
设置文本加粗
// 开启加粗
await printer.setTextBold(handle, true);
await printer.printText(handle, 'Bold Text\n');
// 关闭加粗
await printer.setTextBold(handle, false);
设置文本下划线
// 0 = 无下划线
// 1 = 1点下划线
// 2 = 2点下划线
await printer.setTextUnderline(handle, 1);
await printer.printText(handle, 'Underlined Text\n');
走纸
// 走纸指定行数
await printer.feedLine(handle, 5);
// 走纸指定点数
await printer.feedDot(handle, 100);
切纸
// 半切(虚线切,纸张不完全分离)
await printer.halfCutPaper(handle);
// 全切(实线切,纸张完全分离)
await printer.fullCutPaper(handle);
异常处理
所有端口打开操作在失败时会抛出 PrinterException:
try {
final handle = await printer.openComPort(
portName: '/dev/ttyS0',
baudRate: 115200,
);
} on PrinterException catch (e) {
print('端口打开失败: ${e.code} - ${e.message}');
}
PrinterException 包含以下信息:
| 属性 | 类型 | 说明 |
|---|---|---|
code |
String |
机器可读的错误码,如 INVALID_ARGUMENT, PORT_OPEN_FAILED |
message |
String |
人类可读的错误消息 |
details |
dynamic |
额外的错误详情(可能为 null) |
完整示例
以下是一个完整的票据打印示例:
import 'package:printer/printer.dart';
/// 打印收据示例
Future<void> printReceipt() async {
final printer = Printer();
PrinterPortHandle? portHandle;
try {
// 1. 枚举可用端口
final comPorts = await printer.enumComPorts();
if (comPorts.isEmpty) {
print('没有可用的串口');
return;
}
// 2. 打开第一个可用端口
portHandle = await printer.openComPortWithHandle(
portName: comPorts.first,
baudRate: 115200,
);
final handle = portHandle.handle;
// 3. 设置编码
await printer.setMultiByteMode(handle);
await printer.setMultiByteEncoding(handle, MultiByteEncoding.utf8);
// 4. 打印标题(居中、加粗、放大)
await printer.setAlignment(handle, PrinterAlignment.center);
await printer.setTextBold(handle, true);
await printer.setTextScale(handle, widthScale: 2, heightScale: 2);
await printer.printText(handle, '收据标题\n');
// 5. 重置样式并打印内容
await printer.setTextBold(handle, false);
await printer.setTextScale(handle, widthScale: 1, heightScale: 1);
await printer.setAlignment(handle, PrinterAlignment.left);
await printer.printText(handle, '商品名称 数量 价格\n');
await printer.printText(handle, '----------------------------\n');
await printer.printText(handle, '商品A 2 ¥20.00\n');
await printer.printText(handle, '商品B 1 ¥15.00\n');
await printer.printText(handle, '----------------------------\n');
await printer.printText(handle, '总计: ¥35.00\n');
// 6. 走纸并切纸
await printer.feedLine(handle, 5);
await printer.halfCutPaper(handle);
print('打印完成');
} on PrinterException catch (e) {
print('打印失败: ${e.code} - ${e.message}');
} finally {
// 7. 确保端口关闭
await portHandle?.close();
}
}
API 参考
Printer 类
| 方法 | 返回值 | 说明 |
|---|---|---|
getPlatformVersion() |
Future<String?> |
获取平台版本 |
enumComPorts() |
Future<List<String>> |
枚举可用串口 |
enumUsbPorts() |
Future<List<String>> |
枚举可用USB端口 |
openComPort({...}) |
Future<int> |
打开串口 |
openUsbPort({...}) |
Future<int> |
打开USB端口 |
openComPortWithHandle({...}) |
Future<PrinterPortHandle> |
打开串口并返回安全句柄 |
openUsbPortWithHandle({...}) |
Future<PrinterPortHandle> |
打开USB端口并返回安全句柄 |
closePort(int handle) |
Future<bool> |
关闭端口 |
isPortOpened(int handle) |
Future<bool> |
检查端口是否打开 |
setMultiByteMode(int handle) |
Future<bool> |
设置多字节编码模式 |
setMultiByteEncoding(int, MultiByteEncoding) |
Future<bool> |
设置多字节编码类型 |
printText(int handle, String text) |
Future<bool> |
打印文本 |
setAlignment(int, PrinterAlignment) |
Future<bool> |
设置文本对齐 |
setTextScale(int, {width, height}) |
Future<bool> |
设置文本缩放 |
setTextBold(int handle, bool bold) |
Future<bool> |
设置文本加粗 |
setTextUnderline(int handle, int level) |
Future<bool> |
设置文本下划线 |
feedLine(int handle, int numLines) |
Future<bool> |
走纸指定行数 |
feedDot(int handle, int numDots) |
Future<bool> |
走纸指定点数 |
halfCutPaper(int handle) |
Future<bool> |
半切纸 |
fullCutPaper(int handle) |
Future<bool> |
全切纸 |
枚举类型
SerialParity (串口校验位)
| 值 | 说明 |
|---|---|
none |
无校验 |
odd |
奇校验 |
even |
偶校验 |
mark |
标记校验 |
space |
空白校验 |
SerialStopBits (串口停止位)
| 值 | 说明 |
|---|---|
one |
1位停止位 |
onePointFive |
1.5位停止位 |
two |
2位停止位 |
SerialFlowControl (串口流控制)
| 值 | 说明 |
|---|---|
none |
无流控 |
xonXoff |
XON/XOFF 软件流控 |
rtsCts |
RTS/CTS 硬件流控 |
dtrDsr |
DTR/DSR 硬件流控 |
PrinterAlignment (打印对齐)
| 值 | 说明 |
|---|---|
left |
左对齐 |
center |
居中对齐 |
right |
右对齐 |
MultiByteEncoding (多字节编码)
| 值 | 说明 |
|---|---|
gbk |
GBK 编码(简体中文) |
utf8 |
UTF-8 编码(推荐) |
big5 |
BIG5 编码(繁体中文) |
shiftJis |
Shift-JIS 编码(日文) |
eucKr |
EUC-KR 编码(韩文) |
PrinterPortHandle 类
| 属性/方法 | 类型 | 说明 |
|---|---|---|
handle |
int |
整数端口句柄 |
isValid |
bool |
端口是否仍然有效 |
close() |
Future<void> |
关闭端口,多次调用为 no-op |
PrinterException 类
| 属性 | 类型 | 说明 |
|---|---|---|
code |
String |
错误码 |
message |
String |
错误消息 |
details |
dynamic |
额外详情 |
常见问题
1. 打印乱码怎么办?
- 确认编码设置与发送的文本编码一致,推荐使用
MultiByteEncoding.utf8 - 确认打印机机型是否正确(票据机型使用
CP_Pos_系列函数) - 检查波特率是否与打印机设置一致
2. 端口打开失败?
- 检查端口名称是否正确
- 确认端口未被其他应用占用
- 检查 USB 连接或串口线连接是否正常
3. 打印到一半停止?
- 检查电源是否充足(一般需要 2A 电源)
- 检查是否缺纸