ESC/POS指令 Android端使用示例AI解答微调

# 使用原因

最近由于厂家手持打印机 sdk的升级导致必须适配,但是我们旧用户比较多了已经,app也不会大范围修改了,所以更倾向于 改为通用指令,恰好该厂家支持ESC/POS指令,走蓝牙即可,蓝牙手持机默认连接就行,而我们这个产品恰好是uniapp改动起来比较麻烦,所以准备实现通用插件,我们先用原生实现如下,我们利用as集成的阿里插件对话(不用ds主要是as内插件共享代码比较方便)

# AI关键字对话

1.我是一名安卓开发程序员,现在需要Android开发 通过蓝牙指令 esc指令, 调用安卓设备打印机打印,设备已经固定连接了蓝牙获取已连接蓝牙即可,请打印常见的文字 “商品名 价格明细等内容”纯文字内容即可,请使用kotlin语言开发

2.显示乱码如何处理

outputStream.write(toString().toByteArray(charset("UTF-8")))

3.我想调整打印字体的样式 加粗居中字体大小即可

在蓝牙打印中,文本样式的控制通常依赖于打印机支持的指令集。对于常见的ESC/POS指令集,可以使用特定的转义序列来实现字体修改、加粗、横线、居中等样式。以下是一些常用的指令示例:
字体选择:
选择字体A:0x1B, 0x4D, 0x00
选择字体B:0x1B, 0x4D, 0x01
加粗:
开启加粗:0x1B, 0x45, 0x01
关闭加粗:0x1B, 0x45, 0x00
下划线:
开启下划线(1点宽):0x1B, 0x2D, 0x01
关闭下划线:0x1B, 0x2D, 0x00
居中对齐:
居中对齐:0x1B, 0x61, 0x01
左对齐:0x1B, 0x61, 0x00
右对齐:0x1B, 0x61, 0x02
你可以根据这些指令来修改你的打印文本样式。以下是一个修改后的示例代码,展示了如何在打印文本中应用这些样式

4.为什么UUID是【00001101-0000-1000-8000-00805F9B34FB】是固定的还是随意都可以

UUID 00001101-0000-1000-8000-00805F9B34FB 是一个特定的 UUID,用于蓝牙串口通信(Serial Port Profile, SPP)。这个 UUID 是蓝牙标准中定义的,用于标识蓝牙设备之间的串口通信服务。因此,这个 UUID 不是随便指定的,而是有特定的逻辑和用途。
为什么使用这个 UUID?
标准定义:
00001101-0000-1000-8000-00805F9B34FB 是蓝牙 SIG(Special Interest Group)定义的标准 UUID,用于 SPP 服务。
使用这个 UUID 可以确保你的应用程序能够与支持 SPP 的蓝牙设备进行通信。
兼容性:
大多数蓝牙打印机都支持 SPP 服务,并使用这个 UUID 来标识其串口通信服务。
使用标准 UUID 可以提高应用程序的兼容性,确保能够连接到各种支持 SPP 的蓝牙设备。
其他 UUID
如果你需要连接到其他类型的蓝牙服务,可以使用不同的 UUID。例如:
Handsfree Profile (HFP): 0000111E-0000-1000-8000-00805F9B34FB
Headset Profile (HSP): 00001108-0000-1000-8000-00805F9B34FB
Object Push Profile (OPP): 00001105-0000-1000-8000-00805F9B34FB
总结
标准 UUID: 00001101-0000-1000-8000-00805F9B34FB 是蓝牙标准定义的 SPP 服务 UUID,用于蓝牙串口通信。
逻辑: 这个 UUID 不是随便指定的,而是有特定的用途和标准定义。
兼容性: 使用这个 UUID 可以确保你的应用程序能够与支持 SPP 的蓝牙设备进行通信。
如果你需要连接到其他类型的蓝牙服务,请使用相应的标准 UUID。如果你确实需要自定义 UUID,可以生成一个新的 UUID,但需要确保蓝牙设备也支持该 UUID 并正确配置。

# AI关键字对话

初步使用后 得到乱码 修改为UTF-8后 微调后  代码如下

AndroidManifest.xml

    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <!-- Android 12+ 需要额外声明 -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

申请权限

val perms = arrayOf(
                    Manifest.permission.BLUETOOTH,
                    Manifest.permission.BLUETOOTH_ADMIN,
                    Manifest.permission.BLUETOOTH_CONNECT
                )
            ActivityCompat.requestPermissions(this@SplashActivity, perms, 999)
BluetoothPrinter
package com.zg.quickbase.module.ui.function.print

import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import com.zg.baselibrary.utils.LogUtils.log
import com.zg.baselibrary.utils.ToastUtils
import java.io.IOException
import java.util.UUID

@SuppressLint("MissingPermission")
class BluetoothPrinter {
    fun printReceipt() {
        Thread(Runnable {
            try {
                val printer = findPairedPrinter()
                if (printer == null) {
                    showToast("未找到已连接的打印机")
                    return@Runnable
                }
                val data: Data =
                    Data("123456789", "2023-07-01 12:00:00", "张三", "快递", "商品", "100.00",
                        object : ArrayList<OutboundDetails>() {
                            init {
                                add(OutboundDetails("商品1", "10", "10.00"))
                                add(OutboundDetails("商品2", "20", "20.00"))
                                add(OutboundDetails("商品3", "30", "30.00"))
                            }
                        })
                val socket = printer.createRfcommSocketToServiceRecord(SPP_UUID)
                socket.connect()
                val outputStream = socket.outputStream

                // 初始化打印机
                outputStream.write(byteArrayOf(0x1B, 0x40))
                // 构建打印内容
                val receipt = StringBuilder()
                receipt.run {
                    // 出库单据
                    append(String(byteArrayOf(0x1B, 0x61, 0x01))) // 居中对齐
                    append(String(byteArrayOf(0x1D, 0x21, 0x11))) // 设置字体大小(假设)
                    append("出库单据\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 设置默认字体大小
                    append(String(byteArrayOf(0x1D, 0x21, 0x00)))
                    append(String(byteArrayOf(0x1B, 0x61, 0x00))) // 左对齐

                    // NO:
                    append("NO:" + data.num + "\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 分隔线
                    append("------------------------------\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 时间
                    append("时间:" + data.outTime + "\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 出库人
                    append("出库人:" + data.userName + " 出库方式:" + data.outType + "\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 出库种类
                    append("出库种类:" + data.outboundType + "\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 出库金额
                    append("出库金额: ¥" + data.outboundAmount + "\n")
                    append(String(byteArrayOf(0x0A))) // 换行

                    // 分隔线
                    append(String(byteArrayOf(0x1B, 0x61, 0x01))) // 居中对齐
                    append("------------------------------\n")
                    append(String(byteArrayOf(0x0A))) // 换行
                    append(String(byteArrayOf(0x1B, 0x61, 0x00))) // 左对齐

                    // 出库商品明细
                    append(String(byteArrayOf(0x1B, 0x45, 0x01))) // 开启加粗
                    append("出库商品明细\n")
                    append(String(byteArrayOf(0x0A))) // 换行
                    append(String(byteArrayOf(0x1B, 0x45, 0x00))) // 关闭加粗

                    // 表头 8s 8个字符
                    val header = String.format("%-6s%-8s%-8s\n", "名称", "出库数量", "单价(元)")
                    append(header)

                    // 换行
                    append(String(byteArrayOf(0x0A)))

                    // 商品明细
                    for (outboundDetails in data.outList) {
                        val row = String.format(
                            "%-6s%-8s%-8s\n", outboundDetails.name,
                            "   " + outboundDetails.amount, "   ¥" + outboundDetails.goods_price
                        )
                        append(row)
                    }
                    // 写入输出流
                    outputStream.write(toString().toByteArray(charset("UTF-8")))
                    append(String(byteArrayOf(0x0A))) // 换行
                    // 并切纸(根据打印机型号调整)
                    outputStream.write(byteArrayOf(0x1D, 0x56, 0x41, 0x00)) // 切纸指令
                    outputStream.flush()
                    outputStream.close()
                    socket.close()
                    showToast("打印成功")
                }

            } catch (e: IOException) {
                showToast("打印失败: " + e.message)
                e.printStackTrace()
            }
        }).start()
    }

    private fun findPairedPrinter(): BluetoothDevice? {
        val adapter = BluetoothAdapter.getDefaultAdapter()
        if (adapter == null) {
            showToast("设备不支持蓝牙")
            return null
        }
        val pairedDevices = adapter.getBondedDevices()
        for (device in pairedDevices) {
            if (device != null) {
                log(
                    "device:" + device.getName() + "==" + device.getAddress() + "==" + device.getType()
                            + "==" + device.getUuids()
                )
            }
        }
        for (device in pairedDevices) {
            if (device.getName() != null && device.getName() == PRINTER_NAME) {
                return device
            }
        }
        return null
    }

    // 居中对齐方法
    private fun showToast(message: String) {
        ToastUtils.showToast(message)
    }

    inner class Data(
        var num: String,
        var outTime: String,
        var userName: String,
        var outType: String,
        var outboundType: String,
        var outboundAmount: String,
        outList: ArrayList<OutboundDetails>
    ) {
        var outList: List<OutboundDetails>

        // 构造函数
        init {
            this.outList = outList
        }


    }
    inner class OutboundDetails // 构造函数
        (var name: String, var amount: String, var goods_price: String)
    companion object {
        private val SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
        private const val PRINTER_NAME = "InnerPrinter" // 修改为你的打印机名称
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值