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

Android应用使用ESCPOS热敏打印机库打印阿拉伯字符失败求助

解决ESCPOS-ThermalPrinter-Android打印阿拉伯语不显示的问题

问题根源

阿拉伯语属于RTL(从右到左)语言,且需要打印机支持UTF-8编码才能识别字符。默认的printFormattedText方法未处理阿拉伯语的编码规则与排版逻辑,导致无法正常显示。

具体修改方案

1. 初始化打印机并设置UTF-8编码

在打印操作开始前,明确指定打印机使用UTF-8编码,确保能解析阿拉伯语字符:

val printer = ThermalPrinter(usbConnection, 203, 48f, 3)
printer.setEncoding(Charset.forName("UTF-8"))

2. 添加阿拉伯语文本处理工具函数

阿拉伯语的字符顺序需要调整才能正确打印,使用系统Bidi类处理RTL文本的排版:

private fun processArabicText(text: String): String {
    val bidi = Bidi(text, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT)
    val sb = StringBuilder()
    val runCount = bidi.runCount
    for (i in runCount - 1 downTo 0) {
        val start = bidi.getRunStart(i)
        val end = bidi.getRunEnd(i)
        sb.append(text.substring(start, end))
    }
    return sb.toString()
}

3. 整合到现有打印代码

将所有阿拉伯语文本替换为经过processArabicText处理后的字符串,保留原有的格式标签。

修改后的完整核心代码

private val usbReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (ACTION_USB_PERMISSION == intent.action) {
            synchronized(this) {
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    val usbConnection = UsbPrintersConnections.selectFirstConnected(context)
                    usbConnection?.let { connection ->
                        // 初始化打印机并设置UTF-8编码
                        val printer = ThermalPrinter(connection, 203, 48f, 3)
                        printer.setEncoding(Charset.forName("UTF-8"))

                        // 拼接格式化打印文本,处理所有阿拉伯语文本
                        val formattedText = "[C]<img>" + 
                            PrinterTextParserImg.bitmapToHexadecimalString(printer, 
                                context.resources.getDrawableForDensity(R.drawable.logo, DisplayMetrics.DENSITY_MEDIUM)) +
                            "</img>\n" +
                            "[L]\n" +
                            "[C]" + processArabicText("ريفلو") + "\n" +
                            "[C]" + processArabicText("جده - حي العزيزية") + "\n" +
                            "[C]<u>" + processArabicText("فاتورة ضريبية مبسطة") + "</u>\n" +
                            "[C]<u>Simplified Tax Invoice</u>\n" +
                            "[L]<b>VAT Reg No.</b>[R]310473657600003[R]<b>" + processArabicText("رقم الضريبي") + "</b>\n" +
                            "[L]<b>Invoice No.</b>[R]AT0186[R]<b>" + processArabicText("رقم الفاتورة") + "</b>\n" +
                            "[L]<b>Date</b>[R]13-10-2022 11:05 AM [R]<b>" + processArabicText("تاريخ") + "</b>\n" +
                            "[L]\n" +
                            "[C]--------------------------------\n" +
                            "[L]\n" +
                            "[L]<b>" + processArabicText("البيانـــــــــــات") + "</b>[R]<b>" + processArabicText("كمية") + "</b>[R]<b>" + processArabicText("سعر الوحده") + "</b>[R]<b>" + processArabicText("ضريبة") + "</b>[R]<b>" + processArabicText("الاجمالى") + "</b>\n" +
                            "[L]\n" +
                            "[C]--------------------------------\n" +
                            "[L]" + processArabicText("كوب كبير") + "[R]1[R]21[R]2.74[R]21.00\n" +
                            "[L]Large Cup\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("كوب عادي") + "[R]1[R]11[R]1.43[R]11.00\n" +
                            "[L]Regular Cup\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("كابتشينو") + "[R]1[R]91[R]1.17[R]9.00\n" +
                            "[L]Cappuccino\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("حليب شوكلاته") + "[R]1[R]12[R]1.57[R]12.00\n" +
                            "[L]Milk Choc\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("كوب عادي") + "[R]1[R]11[R]1.43[R]11.00\n" +
                            "[L]Regular Cup\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("بسكويت اطفال") + "[R]1[R]9[R]1.17[R]9.00\n" +
                            "[L]Kids Cone\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("كوب عادي فاخر") + "[R]1[R]15[R]1.96[R]15.00\n" +
                            "[L]Regular Cup Premium\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("بسكويت فاخر") + "[R]1[R]15[R]1.96[R]15.00\n" +
                            "[L]Premium Cone\n" +
                            "[L]\n" +
                            "[C]--------------------------------\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("قيمة المنتجــات") + "[R][R][R][R]89.57\n" +
                            "[L]Products Value ( Excl.VAT)\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("خصم") + "[R][R][R][R]0.00\n" +
                            "[L]Discount(-)\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("ضريبة القيمة المضافة") + "[R][R][R][R]13.43\n" +
                            "[L]VAT (15%)\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("المجموع الكلي") + "[R][R][R][R]103.00\n" +
                            "[L]Grand Total\n" +
                            "[L]\n" +
                            "[L]Total 8 Items\n" +
                            "[C]--------------------------------\n" +
                            "[L] " + processArabicText("المبلغ المدفوع - نقدا") + "[R][R][R][R]3.00\n" +
                            "[L]Amount In Cash\n" +
                            "[L]\n" +
                            "[L]" + processArabicText("لمبلغ المدفوع - البطاقة") + "[R][R][R][R]105.00\n" +
                            "[L]Amount By Card \n" +
                            "[L]\n" +
                            "[L]" + processArabicText("الباقي") + "[R][R][R][R]-5.00\n" +
                            "[L]Balance \n" +
                            "[L]\n" +
                            "[C]<qrcode size='20'>http://www.developpeur-web.dantsu.com/</qrcode>\n" +
                            "[C]****Thank You For Visit Come Again!****"

                        printer.printFormattedText(formattedText)
                        printer.close()
                    }
                } else {
                    Log.d(TAG, "permission denied for device ${usbConnection?.device}")
                }
            }
        }
    }
}

// 处理阿拉伯语文本的工具函数
private fun processArabicText(text: String): String {
    val bidi = Bidi(text, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT)
    val sb = StringBuilder()
    val runCount = bidi.runCount
    for (i in runCount - 1 downTo 0) {
        val start = bidi.getRunStart(i)
        val end = bidi.getRunEnd(i)
        sb.append(text.substring(start, end))
    }
    return sb.toString()
}

fun printUsb(): View.OnClickListener? {
    val usbConnection = UsbPrintersConnections.selectFirstConnected(this)
    val usbManager = this.getSystemService(USB_SERVICE) as UsbManager

    if (usbConnection != null) {
        val permissionIntent = PendingIntent.getBroadcast(
            this,
            0,
            Intent(ACTION_USB_PERMISSION),
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
        )

        val filter = IntentFilter(ACTION_USB_PERMISSION)
        registerReceiver(usbReceiver, filter)
        usbManager.requestPermission(usbConnection.device, permissionIntent)
    }
    return null
}

额外注意事项

  • 确认你的热敏打印机支持UTF-8字符集,若不支持可尝试替换为ISO-8859-6编码(阿拉伯语专用编码)。
  • 部分低端打印机可能无法处理复杂RTL排版,此时可考虑将阿拉伯语文本转为图片后打印。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:45:36