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
相关产品推荐
相关产品推荐

