首页 > 系统 > Android > 正文

Android打印机--小票打印格式及模板设置实例代码

2019-12-12 03:09:51
字体:
来源:转载
供稿:网友

小票打印就是向打印设备发送控制打印格式的指令集,而这些打印格式需要去查询对应打印机的API文档,这里我把常用的api给封装了一下

  1. 文字对齐方式
  2. 打印字体大小
  3. 字体是否加粗
  4. 打印二维码
  5. 打印条形码
  6. 切纸
  7. 打开钱箱
  8. 字符串转字节数组
  9. 字符拼接

PrintFormatUtils.Java

/** * 打印格式 * Created by john on 17-3-23. */public class PrintFormatUtils {  // 对齐方式  public static final int ALIGN_LEFT = 0;   // 靠左  public static final int ALIGN_CENTER = 1;  // 居中  public static final int ALIGN_RIGHT = 2;  // 靠右  //字体大小  public static final int FONT_NORMAL = 0;  // 正常  public static final int FONT_MIDDLE = 1;  // 中等  public static final int FONT_BIG = 2;    // 大  //加粗模式  public static final int FONT_BOLD = 0;       // 字体加粗  public static final int FONT_BOLD_CANCEL = 1;    // 取消加粗  /**   * 打印二维码   * @param qrCode   * @return   */  public static String getQrCodeCmd(String qrCode) {    byte[] data;    int store_len = qrCode.length() + 3;    byte store_pL = (byte) (store_len % 256);    byte store_pH = (byte) (store_len / 256);    // QR Code: Select the model    //       Hex   1D   28   6B   04   00   31   41   n1(x32)   n2(x00) - size of model    // set n1 [49 x31, model 1] [50 x32, model 2] [51 x33, micro qr code]    // https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=140    byte[] modelQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x04, (byte)0x00, (byte)0x31, (byte)0x41, (byte)0x32, (byte)0x00};    // QR Code: Set the size of module    // Hex   1D   28   6B   03   00   31   43   n    // n depends on the printer    // https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=141    byte[] sizeQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x03, (byte)0x00, (byte)0x31, (byte)0x43, (byte)0x08};    //     Hex   1D   28   6B   03   00   31   45   n    // Set n for error correction [48 x30 -> 7%] [49 x31-> 15%] [50 x32 -> 25%] [51 x33 -> 30%]    // https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=142    byte[] errorQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x03, (byte)0x00, (byte)0x31, (byte)0x45, (byte)0x31};    // QR Code: Store the data in the symbol storage area    // Hex   1D   28   6B   pL   pH   31   50   30   d1...dk    // https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=143    //            1D     28     6B     pL     pH cn(49->x31) fn(80->x50) m(48->x30) d1…dk    byte[] storeQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, store_pL, store_pH, (byte)0x31, (byte)0x50, (byte)0x30};    // QR Code: Print the symbol data in the symbol storage area    // Hex   1D   28   6B   03   00   31   51   m    // https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=144    byte[] printQR = {(byte)0x1d, (byte)0x28, (byte)0x6b, (byte)0x03, (byte)0x00, (byte)0x31, (byte)0x51, (byte)0x30};    data = byteMerger(modelQR, sizeQR);    data = byteMerger(data, errorQR);    data = byteMerger(data, storeQR);    data = byteMerger(data, qrCode.getBytes());    data = byteMerger(data, printQR);    return new String(data);  }  /**   * 打印条码   * @param barcode   * @return   */  public static String getBarcodeCmd(String barcode) {    // 打印 Code-128 条码时需要使用字符集前缀    // "{A" 表示大写字母    // "{B" 表示所有字母,数字,符号    // "{C" 表示数字,可以表示 00 - 99 的范围    byte[] data;    String btEncode;    if (barcode.length() < 18) {      // 字符长度小于15的时候直接输出字符串      btEncode = "{B" + barcode;    } else {      // 否则做一点优化      int startPos = 0;      btEncode = "{B";      for (int i = 0; i < barcode.length(); i++) {        char curChar = barcode.charAt(i);        if (curChar < 48 || curChar > 57 || i == (barcode.length() - 1)) {          // 如果是非数字或者是最后一个字符          if (i - startPos >= 10) {            if (startPos == 0) {              btEncode = "";            }            btEncode += "{C";            boolean isFirst = true;            int numCode = 0;            for (int j = startPos; j < i; j++) {              if (isFirst) { // 处理第一位                numCode = (barcode.charAt(j) - 48) * 10;                isFirst = false;              } else { // 处理第二位                numCode += (barcode.charAt(j) - 48);                btEncode += (char) numCode;                isFirst = true;              }            }            btEncode += "{B";            if (!isFirst) {              startPos = i - 1;            } else {              startPos = i;            }          }          for (int k = startPos; k <= i; k++) {            btEncode += barcode.charAt(k);          }          startPos = i + 1;        }      }    }    // 设置 HRI 的位置,02 表示下方    byte[] hriPosition = {(byte) 0x1d, (byte) 0x48, (byte) 0x02};    // 最后一个参数表示宽度 取值范围 1-6 如果条码超长则无法打印    byte[] width = {(byte) 0x1d, (byte) 0x77, (byte) 0x02};    byte[] height = {(byte) 0x1d, (byte) 0x68, (byte) 0xfe};    // 最后两个参数 73 : CODE 128 || 编码的长度    byte[] barcodeType = {(byte) 0x1d, (byte) 0x6b, (byte) 73, (byte) btEncode.length()};    byte[] print = {(byte) 10, (byte) 0};    data = PrintFormatUtils.byteMerger(hriPosition, width);    data = PrintFormatUtils.byteMerger(data, height);    data = PrintFormatUtils.byteMerger(data, barcodeType);    data = PrintFormatUtils.byteMerger(data, btEncode.getBytes());    data = PrintFormatUtils.byteMerger(data, print);    return new String(data);  }  /**   * 切纸   * @return   */  public static String getCutPaperCmd() {    // 走纸并切纸,最后一个参数控制走纸的长度    byte[] data = {(byte) 0x1d, (byte) 0x56, (byte) 0x42, (byte) 0x15};    return new String(data);  }  /**   * 对齐方式   * @param alignMode   * @return   */  public static String getAlignCmd(int alignMode) {    byte[] data = {(byte) 0x1b, (byte) 0x61, (byte) 0x0};    if (alignMode == ALIGN_LEFT) {      data[2] = (byte) 0x00;    } else if (alignMode == ALIGN_CENTER) {      data[2] = (byte) 0x01;    } else if (alignMode == ALIGN_RIGHT) {      data[2] = (byte) 0x02;    }    return new String(data);  }  /**   * 字体大小   * @param fontSize   * @return   */  public static String getFontSizeCmd(int fontSize) {    byte[] data = {(byte) 0x1d, (byte) 0x21, (byte) 0x0};    if (fontSize == FONT_NORMAL) {      data[2] = (byte) 0x00;    } else if (fontSize == FONT_MIDDLE) {      data[2] = (byte) 0x01;    } else if (fontSize == FONT_BIG) {      data[2] = (byte) 0x11;    }    return new String(data);  }  /**   * 加粗模式   * @param fontBold   * @return   */  public static String getFontBoldCmd(int fontBold) {    byte[] data = {(byte) 0x1b, (byte) 0x45, (byte) 0x0};    if (fontBold == FONT_BOLD) {      data[2] = (byte) 0x01;    } else if (fontBold == FONT_BOLD_CANCEL) {      data[2] = (byte) 0x00;    }    return new String(data);  }  /**   * 打开钱箱   * @return   */  public static String getOpenDrawerCmd() {    byte[] data = new byte[4];    data[0] = 0x10;    data[1] = 0x14;    data[2] = 0x00;    data[3] = 0x00;    return new String(data);  }  /**   * 字符串转字节数组   * @param str   * @return   */  public static byte[] stringToBytes(String str) {    byte[] data = null;    try {      byte[] strBytes = str.getBytes("utf-8");      data = (new String(strBytes, "utf-8")).getBytes("gbk");    } catch (UnsupportedEncodingException exception) {      exception.printStackTrace();    }    return data;  }  /**   * 字节数组合并   * @param bytesA   * @param bytesB   * @return   */  public static byte[] byteMerger(byte[] bytesA, byte[] bytesB) {    byte[] bytes = new byte[bytesA.length + bytesB.length];    System.arraycopy(bytesA, 0, bytes, 0, bytesA.length);    System.arraycopy(bytesB, 0, bytes, bytesA.length, bytesB.length);    return bytes;  }}

有了打印格式,还要对具体的打印小票设置打印模板,主要就是利用上面的打印格式工具类,进行字符或字符串拼接,设置文字间空格的长度,以及使用换行符换行等。

有些小票打印的内容有可能是通用的,比如底部结束语可能是公司宣传语或广告语,这些内容是否展示需要根据具体需求加以控制,还有二维码、条形码打印,是否切纸等需要根据实际场景取舍,所以最好封装一个打印配置类,以控制打印内容显示。

/** * 打印模板 */public class PrintContract {  /**   * 打印内容   */  public static StringBuilder createXxTxt(String ...) {    StringBuilder builder = new StringBuilder();    //设置大号字体以及加粗    builder.append(PrintFormatUtils.getFontSizeCmd(PrintFormatUtils.FONT_BIG));    builder.append(PrintFormatUtils.getFontBoldCmd(PrintFormatUtils.FONT_BOLD));    // 标题    builder.append("Title");    //换行,调用次数根据换行数来控制    addLineSeparator(builder);    //设置普通字体大小、不加粗    builder.append(PrintFormatUtils.getFontSizeCmd(PrintFormatUtils.FONT_NORMAL));    builder.append(PrintFormatUtils.getFontBoldCmd(PrintFormatUtils.FONT_BOLD_CANCEL));    //内容    ......    //设置某两列文字间空格数, x需要计算出来    addIdenticalStrToStringBuilder(builder, x, " ");    //切纸    builder.append(PrintFormatUtils.getCutPaperCmd());    return builder;  }  /**   * 向StringBuilder中添加指定数量的相同字符   *   * @param printCount  添加的字符数量   * @param identicalStr 添加的字符   */  private static void addIdenticalStrToStringBuilder(StringBuilder builder, int printCount, String identicalStr) {    for (int i = 0; i < printCount; i++) {      builder.append(identicalStr);    }  }  /**   * 根据字符串截取前指定字节数,按照GBK编码进行截取   *   * @param str 原字符串   * @param len 截取的字节数   * @return 截取后的字符串   */  private static String subStringByGBK(String str, int len) {    String result = null;    if (str != null) {      try {        byte[] a = str.getBytes("GBK");        if (a.length <= len) {          result = str;        } else if (len > 0) {          result = new String(a, 0, len, "GBK");          int length = result.length();          if (str.charAt(length - 1) != result.charAt(length - 1)) {            if (length < 2) {              result = null;            } else {              result = result.substring(0, length - 1);            }          }        }      } catch (Exception e) {        e.printStackTrace();      }    }    return result;  }  /**   * 添加换行符   */  private static void addLineSeparator(StringBuilder builder) {    builder.append("/n");  }  /**   * 在GBK编码下,获取其字符串占据的字符个数   */  private static int getCharCountByGBKEncoding(String text) {    try {      return text.getBytes("GBK").length;    } catch (Exception e) {      e.printStackTrace();      return 0;    }  }  /**  * 打印相关配置  */  public static class PrintConfig {    public int maxLength = 30;    public boolean printBarcode = false; // 打印条码    public boolean printQrCode = false;  // 打印二维码    public boolean printEndText = true;  // 打印结束语    public boolean needCutPaper = false; // 是否切纸  }}

有了打印模板,接下来就是调用打印设备打印方法发送打印指令

//调用打印机打印方法,传入上面某个小票打印模板返回的字符串String str = PrintContract.createXxTxt(...);printer.print(str, null);//打开钱箱方法printer.print(PrintFormatUtils.getOpenDrawerCmd(), null);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表