uniapp使用plus调取蓝牙/usb打印

发布于:2025-06-30 ⋅ 阅读:(20) ⋅ 点赞:(0)

 安卓使用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;


网站公告

今日签到

点亮在社区的每一天
去签到