安卓使用usb调取打印机
/*** 安卓usb调取打印机*@param { string | bytes[] } html 传入的打印内容*传入一段文本或一个bytes数组* @returns*/
export const printUsb = (html) => {return new Promise((resolve, reject) => {if (!window.plus) return reject(new Error("请在安卓环境中使用!"));//如果参数不是字符串或bytes数组直接报错if (!Array.isArray(html) && typeof html !== "string")return reject(new Error("参数不正确!"));try {const context = plus.android.runtimeMainActivity();const usbManager = context.getSystemService("usb");//引入usb类plus.android.importClass(usbManager);//获取到设备列表const devices = usbManager.getDeviceList();const values = plus.android.invoke(devices, "values");//调用values方法获取usb设备列表const deviceList = plus.android.invoke(values, "toArray");const printerList = deviceList.filter((item) => {const usbInterface = plus.android.invoke(item, "getInterface", 0);const usbType = plus.android.invoke(usbInterface, "getInterfaceClass");//usb类型为7的时候是打印机if (usbType === 7) return item;});//如果打印机不存在,直接阻断if (!printerList.length) return reject(new Error("请连接打印机设备!"));//usb设备(我这里选择打印机的第一台连接,如果要连多台打印机可以用上面获取的pinterList打印机列表进行操作)const device = printerList[0];const PendingIntent = plus.android.importClass("android.app.PendingIntent",);const Intent = plus.android.importClass("android.content.Intent");//申请usb传输权限const pendingIntent = PendingIntent.getBroadcast(context,0,new Intent("ACTION_USB_PERMISSION"),PendingIntent.FLAG_UPDATE_CURRENT,);//判断是否具有权限const isExist = plus.android.invoke(usbManager, "hasPermission", device);//如果权限不存在申请权限if (!isExist) {//请求读写权限usbManager.requestPermission(device, pendingIntent);return resolve('已获取usb权限!');}//建立连接const socket = usbManager.openDevice(device);if (!socket) return reject(new Error("usb连接失败!"));const iface = plus.android.invoke(device, "getInterface", 0);plus.android.invoke(socket, "claimInterface", iface, true);//批量传输示例const endpoint = plus.android.invoke(iface, "getEndpoint", 0);//根据传入的内容类型做处理const buffer =typeof html === "string"? plus.android.invoke(html, "getBytes", "gbk"): html;plus.android.invoke(socket,"bulkTransfer",endpoint,buffer,buffer.length,5000,);//释放usb端口资源plus.android.invoke(socket, "releaseInterface", iface);//关闭usb连接plus.android.invoke(socket, "close");resolve("打印成功!");} catch (error) {reject(error);}});
};
安卓使用蓝牙调取打印机设备
/**
*安卓使用蓝牙调取打印机
*@param { string } deviceId 蓝牙的mac地址(即设备id)
*@param { string } html 需要打印的文本
*/
export const printBluetooth(deviceId, html) {return new Promise((resolve, reject) => {try {plus.android.runtimeMainActivity();const BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter",);const UUID = plus.android.importClass("java.util.UUID");const uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");const Adapter = BluetoothAdapter.getDefaultAdapter();Adapter.cancelDiscovery(); //停止扫描const device = Adapter.getRemoteDevice(deviceId);plus.android.importClass(device);const bluetoothSocket =device.createInsecureRfcommSocketToServiceRecord(uuid);plus.android.importClass(bluetoothSocket);if (!bluetoothSocket.isConnected()) {bluetoothSocket.connect();}const outputStream = bluetoothSocket.getOutputStream();plus.android.importClass(outputStream);const bytes = plus.android.invoke(html, "getBytes", "gbk");outputStream.write(bytes);outputStream.flush();outputStream.close();resolve();} catch (error) {reject(error);}});
}
热敏打印机配置参数及简单模板
(部分命令可能不一致,需要查找对应品牌的打印机指令)
const printer = {//初始化打印机start: "\x1B\x40",//左边距leftPadding: "\x1D\x4C\x02\x00",//右边距rightPadding: "\x1D\x57\x02\x00",//首行缩进两字符textIndent:'\x1B\x5C\x18\x00',//文本左对齐alignLeft: "\x1B\x61\x00",//文本居中alignCenter: "\x1B\x61\x01",//文本右对齐alignRight: "\x1B\x61\x02",//字体缩小textSmall: "\x1B\x21\x00",//字体放大textLarge: "\x1D\x21\x11",//恢复默认字体textRecover: "\x1D\x21\x00",//字体加粗bold: "\x1B\x45\x01",//取消字体加粗boldOff: "\x1B\x45\x00",//字体双倍高度doubleHeight: "\x1B\x33\x30",//恢复行高lineHeightRecover: "\x1B\x32",//设置行间距lineSpacing: `\x1B\x33\x24`,//换行lineBreak: "\x0A",//禁止自动换行tabOff: "\x1B\x57\x00",//恢复自动换行tab: "\x1B\x31\x01",//切纸 (全切)end: "\x1B\x69",//切纸 (半切)endHalf: "\x1B\x6D",//分割线devide: `\x1B\x61\x01${"-".repeat(48)}\x0A\x1B\x61\x00`,//二维码qrcode: () => {return;},
};//计算中间空白间隔
function letterSpace(str) {const length = [...str].reduce((acc, char) => //中文unicode编码大于255(中文一个字占2个字符,英文一个字一字符)acc + (char.charCodeAt(0) > 255 ? 2 : 1), 0)//80mm热敏打印机减去左右边距宽度为48字符return ' '.repeat(48 - length);
}const createTemplate = () => {
let escpos = `${printer.start}
${printer.alignCenter}${printer.bold}哆啦A梦餐厅
${printer.lineBreak}
${printer.alignCenter}${printer.bold}【收银凭证】${printer.lineBreak}
${printer.alignLeft}${printer.bold}贵宾客户${printer.lineBreak}
${printer.alignLeft}${printer.boldOff}2025/06/27 09:18${letterSpace('2025/06/27 09:18票号:0007')}${printer.bold}票号:0007${printer.lineBreak}
${printer.devide}
${printer.bold}1.麻婆豆腐${letterSpace('1.麻婆豆腐72元')}${printer.bold}72元${printer.lineBreak}
${printer.textSmall}${printer.textIndent}8件x9${printer.lineBreak}
${printer.devide}
${printer.textSmall}应付${letterSpace('应付72元')}${printer.bold}72元${printer.lineBreak}
${printer.textSmall}实付${letterSpace('实付(现金)72元')}${printer.bold}(现金)72元${printer.lineBreak}
${printer.devide}
${printer.textSmall}收银员:哆啦美${printer.lineBreak}
${printer.end}
`;// 行4 (空行)return escpos;
};export default createTemplate;