You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter Android项目USB POS打印机(Epson TM-T20)打印:寻求flutter_usb_write的替代方案

替代flutter_usb_write实现USB POS打印的方案

我明白你在使用flutter_usb_write时遇到的这些糟心事——写入失败、包本身缺乏维护、不支持空安全,这些问题确实会让开发卡壳。针对Epson TM-T20这类USB POS打印机,这里有几个更靠谱的替代方案,你可以试试:

1. 使用usb_serial

这个包是Flutter生态里比较成熟的USB串口通信工具,支持空安全,社区活跃度也不错。对于Epson打印机,你可以通过它发送原始ESC/POS指令,完全满足原始字节打印的需求。

示例代码:

import 'package:usb_serial/usb_serial.dart';

Future<void> printWithUsbSerial(String text) async {
  // 获取设备列表,筛选Epson TM-T20
  List<UsbDevice> devices = await UsbSerial.listDevices();
  UsbDevice? printerDevice = devices.firstWhere(
    (device) => device.productName?.contains("TM-T20") ?? false,
    orElse: () => throw Exception("Printer not found"),
  );

  // 打开设备连接
  UsbPort? port = await printerDevice.create();
  if (!(await port!.open())) {
    print("Failed to open printer port");
    return;
  }

  // 配置串口参数(Epson TM-T20默认参数:9600波特率、8数据位、1停止位、无校验)
  await port.setParameters(9600, UsbPort.DATABITS_8, UsbPort.STOPBITS_1, UsbPort.PARITY_NONE);

  // 准备打印数据:先发送初始化指令,再追加文本和换行
  Uint8List printData = Uint8List.fromList(
    [27, 64] // ESC @ 指令:初始化打印机
      .followedBy(text.codeUnits)
      .followedBy([10, 10]) // 追加两次换行,避免内容粘连
      .toList(),
  );

  // 发送打印数据
  int bytesWritten = await port.write(printData);
  print("Successfully wrote $bytesWritten bytes to printer");

  // 关闭连接
  await port.close();
}

注意事项:

  • 需要在AndroidManifest.xml中添加USB权限配置:
    <uses-feature android:name="android.hardware.usb.host" />
    <uses-permission android:name="android.permission.USB_PERMISSION" />
    
  • 首次连接打印机时,系统会弹出USB权限授权弹窗,需要用户确认。

2. 直接调用Android原生代码(通过MethodChannel)

如果Flutter包都不能满足你的定制需求,直接写Android原生的USB通信代码是最灵活的方案,完全可控,还能避开第三方包的坑。

大致实现步骤:

  1. 在Android项目中创建USB打印服务类,使用Android原生的UsbManagerUsbDeviceConnection等API实现打印机通信。
  2. 通过Flutter的MethodChannel将打印方法暴露给Dart层。
  3. 在Dart层调用原生方法完成打印。

原生代码示例(Kotlin):

class UsbPrinterHelper(private val context: Context) {
    private val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager
    private val ACTION_USB_PERMISSION = "com.your.app.package.USB_PERMISSION"

    fun printText(text: String): Boolean {
        // 查找Epson TM-T20设备
        val printerDevice = usbManager.deviceList.values.firstOrNull {
            it.productName?.contains("TM-T20") == true
        } ?: return false

        // 请求USB权限
        val permissionIntent = PendingIntent.getBroadcast(
            context,
            0,
            Intent(ACTION_USB_PERMISSION),
            PendingIntent.FLAG_IMMUTABLE
        )
        usbManager.requestPermission(printerDevice, permissionIntent)

        // 打开设备连接
        val connection = usbManager.openDevice(printerDevice) ?: return false
        val printerInterface = printerDevice.getInterface(0)
        val outputEndpoint = printerInterface.getEndpoint(0)

        // 组装打印数据:初始化指令 + 文本 + 换行
        val initBytes = byteArrayOf(27, 64) // ESC @ 初始化
        val textBytes = text.toByteArray() + byteArrayOf(10, 10)
        val printBytes = initBytes + textBytes

        // 发送数据到打印机
        connection.claimInterface(printerInterface, true)
        val bytesWritten = connection.bulkTransfer(outputEndpoint, printBytes, printBytes.size, 5000)
        connection.releaseInterface(printerInterface)
        connection.close()

        // 返回是否全部字节写入成功
        return bytesWritten == printBytes.size
    }
}

之后在Flutter层通过MethodChannel调用这个printText方法即可。

3. 封装Epson官方原生SDK

Epson有针对Android的官方ePOS SDK,虽然没有直接的Flutter插件,但你可以通过MethodChannel封装原生SDK的功能。这种方式的优势是能完美适配Epson打印机,支持更多高级功能(比如切纸、条形码打印、图形打印等)。

实现思路:

  1. 下载并集成Android版Epson ePOS SDK到你的Flutter Android项目中。
  2. 封装SDK中的打印方法,通过MethodChannel暴露给Dart层。
  3. 在Flutter层调用封装好的方法完成打印。

另外,针对你当前使用flutter_usb_write遇到的问题,也可以简单排查下:比如是否正确申请了USB权限、是否指定了打印机的正确端点(部分打印机需要特定的bulk端点)、发送的数据是否符合ESC/POS规范。但考虑到这个包的维护状态,还是建议切换到上面更可靠的方案。

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

火山引擎 最新活动