Android打印機--小票打印格式及模板設(shè)置實例代碼
小票打印就是向打印設(shè)備發(fā)送控制打印格式的指令集,而這些打印格式需要去查詢對應(yīng)打印機的API文檔,這里我把常用的api給封裝了一下
- 文字對齊方式
- 打印字體大小
- 字體是否加粗
- 打印二維碼
- 打印條形碼
- 切紙
- 打開錢箱
- 字符串轉(zhuǎn)字節(jié)數(shù)組
- 字符拼接
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" 表示所有字母,數(shù)字,符號
// "{C" 表示數(shù)字,可以表示 00 - 99 的范圍
byte[] data;
String btEncode;
if (barcode.length() < 18) {
// 字符長度小于15的時候直接輸出字符串
btEncode = "{B" + barcode;
} else {
// 否則做一點優(yōu)化
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)) {
// 如果是非數(shù)字或者是最后一個字符
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;
}
}
}
// 設(shè)置 HRI 的位置,02 表示下方
byte[] hriPosition = {(byte) 0x1d, (byte) 0x48, (byte) 0x02};
// 最后一個參數(shù)表示寬度 取值范圍 1-6 如果條碼超長則無法打印
byte[] width = {(byte) 0x1d, (byte) 0x77, (byte) 0x02};
byte[] height = {(byte) 0x1d, (byte) 0x68, (byte) 0xfe};
// 最后兩個參數(shù) 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() {
// 走紙并切紙,最后一個參數(shù)控制走紙的長度
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);
}
/**
* 字符串轉(zhuǎn)字節(jié)數(shù)組
* @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;
}
/**
* 字節(jié)數(shù)組合并
* @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;
}
}
有了打印格式,還要對具體的打印小票設(shè)置打印模板,主要就是利用上面的打印格式工具類,進行字符或字符串拼接,設(shè)置文字間空格的長度,以及使用換行符換行等。
有些小票打印的內(nèi)容有可能是通用的,比如底部結(jié)束語–可能是公司宣傳語或廣告語,這些內(nèi)容是否展示需要根據(jù)具體需求加以控制,還有二維碼、條形碼打印,是否切紙等需要根據(jù)實際場景取舍,所以最好封裝一個打印配置類,以控制打印內(nèi)容顯示。
/**
* 打印模板
*/
public class PrintContract {
/**
* 打印內(nèi)容
*/
public static StringBuilder createXxTxt(String ...) {
StringBuilder builder = new StringBuilder();
//設(shè)置大號字體以及加粗
builder.append(PrintFormatUtils.getFontSizeCmd(PrintFormatUtils.FONT_BIG));
builder.append(PrintFormatUtils.getFontBoldCmd(PrintFormatUtils.FONT_BOLD));
// 標題
builder.append("Title");
//換行,調(diào)用次數(shù)根據(jù)換行數(shù)來控制
addLineSeparator(builder);
//設(shè)置普通字體大小、不加粗
builder.append(PrintFormatUtils.getFontSizeCmd(PrintFormatUtils.FONT_NORMAL));
builder.append(PrintFormatUtils.getFontBoldCmd(PrintFormatUtils.FONT_BOLD_CANCEL));
//內(nèi)容
......
//設(shè)置某兩列文字間空格數(shù), x需要計算出來
addIdenticalStrToStringBuilder(builder, x, " ");
//切紙
builder.append(PrintFormatUtils.getCutPaperCmd());
return builder;
}
/**
* 向StringBuilder中添加指定數(shù)量的相同字符
*
* @param printCount 添加的字符數(shù)量
* @param identicalStr 添加的字符
*/
private static void addIdenticalStrToStringBuilder(StringBuilder builder, int printCount, String identicalStr) {
for (int i = 0; i < printCount; i++) {
builder.append(identicalStr);
}
}
/**
* 根據(jù)字符串截取前指定字節(jié)數(shù),按照GBK編碼進行截取
*
* @param str 原字符串
* @param len 截取的字節(jié)數(shù)
* @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編碼下,獲取其字符串占據(jù)的字符個數(shù)
*/
private static int getCharCountByGBKEncoding(String text) {
try {
return text.getBytes("GBK").length;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 打印相關(guān)配置
*/
public static class PrintConfig {
public int maxLength = 30;
public boolean printBarcode = false; // 打印條碼
public boolean printQrCode = false; // 打印二維碼
public boolean printEndText = true; // 打印結(jié)束語
public boolean needCutPaper = false; // 是否切紙
}
}
有了打印模板,接下來就是調(diào)用打印設(shè)備打印方法發(fā)送打印指令
//調(diào)用打印機打印方法,傳入上面某個小票打印模板返回的字符串 String str = PrintContract.createXxTxt(...); printer.print(str, null); //打開錢箱方法 printer.print(PrintFormatUtils.getOpenDrawerCmd(), null);
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android實現(xiàn)PDF預覽打印功能
- Android gradle插件打印時間戳的方法詳解
- Android編程實現(xiàn)計算兩個日期之間天數(shù)并打印所有日期的方法
- Android中如何安全地打印日志詳解
- Mac 下 Android Studio 不打印日志的解決辦法
- Android jni調(diào)試打印char陣列的實例詳解
- Android下的POS打印機調(diào)用的簡單實現(xiàn)
- Android 藍牙連接 ESC/POS 熱敏打印機打印實例(ESC/POS指令篇)
- Android 藍牙連接 ESC/POS 熱敏打印機打印實例(藍牙連接篇)
- Android進階——安卓調(diào)用ESC/POS打印機打印實例
- Android手機通過藍牙連接佳博打印機的實例代碼
- Android實現(xiàn)系統(tǒng)打印功能
相關(guān)文章
Android開發(fā)之圖形圖像與動畫(二)Animation實現(xiàn)圖像的漸變/縮放/位移/旋轉(zhuǎn)
Android 平臺提供了兩類動畫,一類是Tween動畫,就是對場景里的對象不斷的進行圖像變化來產(chǎn)生動畫效果;旋轉(zhuǎn)、平移、放縮和漸變等等,感興趣的朋友可以了解下啊,希望本文對你有所幫助2013-01-01
Android中判斷網(wǎng)絡(luò)是否連接實例詳解
這篇文章主要介紹了Android中判斷網(wǎng)絡(luò)是否連接實例詳解的相關(guān)資料,需要的朋友可以參考下2017-01-01
Android 自定義TextView實現(xiàn)文本內(nèi)容自動調(diào)整字體大小
本文主要介紹了Android 自定義TextView實現(xiàn)文本內(nèi)容自動調(diào)整字體大小以適應(yīng)TextView的大小的方法。具有很好的參考價值。下面跟著小編一起來看下吧2017-03-03
Android圖片三級緩存策略(網(wǎng)絡(luò)、本地、內(nèi)存緩存)
這篇文章主要介紹了Android圖片三級緩存策略(網(wǎng)絡(luò)、本地、內(nèi)存緩存)的相關(guān)資料,需要的朋友可以參考下2016-04-04

