Android--連接USB打印機(jī)

訪客機(jī)或消費(fèi)機(jī)等設(shè)備有連接打印機(jī)打印小票的需求,本篇記錄一下設(shè)備連接USB打印機(jī)打印小票內(nèi)容的功能實(shí)現(xiàn)。

其中涉及的工具類(lèi)包括Other.java、Command.java、PrinterCommand.java和PrinterController.java

連接USB打印機(jī)

1. Other.java類(lèi)

該工具類(lèi)中只包含一個(gè)方法,用于將byteArrays數(shù)據(jù)轉(zhuǎn)換為Bytes數(shù)據(jù)。

public class Other {
    public static byte[] byteArraysToBytes(byte[][] data) {
        int length = 0;

        for (byte[] datum : data) {
            length += datum.length;
        }

        byte[] send = new byte[length];
        int k = 0;

        for (byte[] datum : data) {
            for (byte b : datum) {
                send[k++] = b;
            }
        }

        return send;
    }
}

2. Command.java類(lèi)

該類(lèi)主要定義打印機(jī)所需的指令。

/**
 * 打印機(jī)指令
 */
public class Command {

    //打印機(jī)初始化
    public static byte[] ESC_Init = new byte[] {0x1b, 0x40 };

    //實(shí)時(shí)狀態(tài)傳送指令
    public static byte[] DLE_eot = new byte[] {0x10, 0x04, 0x04 };
    //實(shí)時(shí)狀態(tài)傳送指令 查詢1 打印機(jī)
    public static final byte[] DLE_eot1 = new byte[] {0x10, 0x04, 0x01};
    //實(shí)時(shí)狀態(tài)傳送指令 查詢2 脫機(jī)
    public static final byte[] DLE_eot2 = new byte[] {0x10, 0x04, 0x02};
    //實(shí)時(shí)狀態(tài)傳送指令 查詢3 錯(cuò)誤
    public static final byte[] DLE_eot3 = new byte[] {0x10, 0x04, 0x03};
    //實(shí)時(shí)狀態(tài)傳送指令 查詢4 卷紙傳感器
    public static final byte[] DLE_eot4 = new byte[] {0x10, 0x04, 0x04};

    //獲取打印機(jī)打印狀態(tài)  測(cè)試
    public static final byte[] ESC_STATUS = new byte[] {0x1B, 0x76};

    //設(shè)置對(duì)齊模式
    public static byte[] ESC_Align = new byte[] {0x1b, 0x61, 0x00 };
    //設(shè)置字體加粗
    public static final byte[] ESC_BOLD = new byte[] {0x1b, 0x45,0x01};

    //橫向放大
    public static final byte[] ESC_GS_H = new byte[] {0x1b, 0x55, 0x00};
    //縱向放大
    public static final byte[] ESC_GS_O = new byte[] {0x1b, 0x56, 0x00};
    //橫向縱向放大
    public static final byte[] ESC_GS_O_H = new byte[] {0x1b, 0x57, 0x00};

    //換行
    public static final byte[] ESC_WRAP= new byte[] {0x0A};
    //回車(chē)
    public static final byte[] ESC_ENTER= new byte[] {0x0D};
    //走紙N行, 最后一位是行數(shù),默認(rèn)一行
    public static final byte[] ESC_Paper = new byte[] {0x1B, 0x64, 0x01};

    //簡(jiǎn)體中文字符集
    public static final byte[] ESC_Chinese = new byte[] {0x1c, 0x26, 0x1b, 0x74, 0x00};
}

3. PrinterCommand.java類(lèi)

該類(lèi)提供打印功能,包括打印機(jī)初始化、設(shè)置打印格式等功能。

public class PrinterCommand {
    /**
     * 打印機(jī)初始化
     */
    public byte[] POS_Set_PrtInit() {

        return Other.byteArraysToBytes(new byte[][]{Command.ESC_Init});
    }

    /**
     * 設(shè)置對(duì)齊模式
     *
     * @param align 0 左對(duì)齊, 1 居中, 2 右對(duì)齊
     * @return 打印機(jī)字節(jié)
     */
    public byte[] POS_S_Align(int align) {
        if (align < 0 || align > 2) {
            return null;
        }
        byte[] data = Command.ESC_Align;
        data[2] = (byte) align;
        return data;
    }

    /**
     * 換行
     * @param count 換行行數(shù)1-10
     * @return
     */
    public  byte[] POS_S_PrintLine(int count){
        if(count <= 0) count = 1;
        if(count >= 10) count = 10;

        byte[] data = Command.ESC_Paper;
        data[2] = (byte) count;
        return data;
    }

    /**
     * 橫向放大
     * @param font_size 放大尺寸
     * @return
     */
    public byte[] POS_S_GS_H(int font_size) {
        if (font_size <= 0) font_size = 0;
        if (font_size >= 7) font_size = 7;
        byte[] data = Command.ESC_GS_H;
        data[2] = (byte) (font_size );
        return data;
    }

    /**
     * 縱向放大
     * @param font_size 放大尺寸
     * @return
     */
    public byte[] POS_S_GS_O(int font_size) {
        if (font_size <= 0) font_size = 0;
        if (font_size >= 7) font_size = 7;
        byte[] data = Command.ESC_GS_O;
        data[2] = (byte) (font_size );
        return data;
    }

    /**
     * 橫向縱向同時(shí)放大
     * @param font_size 放大尺寸
     * @return
     */
    public  byte[] POS_S_GS_O_H(int font_size) {
        if (font_size <= 0) font_size = 0;
        if (font_size >= 7) font_size = 7;
        byte[] data = Command.ESC_GS_O_H;
        data[2] = (byte) ( font_size );
        return data;
    }

    /**
     * 加粗
     * @return
     */
    public byte[] Set_Bold(){
        byte[] data = Command.ESC_BOLD;
        data[2] = (byte) (1);
        return data;
    }

    /**
     * 換行
     * @return
     */
    public byte[] POS_Set_Enter(){
        return Command.ESC_ENTER;
    }

}

4. PrinterController.java類(lèi)

該類(lèi)為打印控制類(lèi),提供了打印機(jī)連接、打印內(nèi)容、監(jiān)聽(tīng)usb打印機(jī)連接狀態(tài)等接口。

public class PrinterController extends BroadcastReceiver {

    private static final String TAG = "PrinterController";
    private Context appContext;
    private UsbManager mUsbManager;
    // 我們的發(fā)送端、打印機(jī)的接收端
    private UsbEndpoint epOut;
    // 我們的讀取端、打印機(jī)的發(fā)送端
    private UsbEndpoint epIn;
    private UsbInterface usbIf;
    private UsbDeviceConnection conn;
    private UsbDevice dev;

    private static final int LINE_BYTE_SIZE = 48;

    public static final String PRINTER = "printer";
    public static final String MICRO_PRINTER = "micro printer";
    public static final String FMT_YYYY_MM_DD_HH_MM2 = "yyyy-MM-dd HH:mm";
    public static final String ACTION_USB_PERMISSION = "com.zj.usbconn.USB";

    private static final PrinterController INSTANCE = new PrinterController();

    public PrinterController() {}

    public static PrinterController getInstance() {
        return INSTANCE;
    }

    public void getPrinterContext(Context context) {
        appContext = context;
        mUsbManager = (UsbManager) appContext.getSystemService(Context.USB_SERVICE);
    }

    public final synchronized void connect(UsbDevice dev) {
        close();
        PrinterController.getInstance().dev = dev;
        if (!this.isHasPermission(dev)) {
            this.getPermission(dev);
            Toast.makeText(appContext, "打印機(jī)無(wú)權(quán)限", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "打印機(jī)無(wú)權(quán)限getPermission");
        } else {
            Toast.makeText(appContext, "打印機(jī)連接成功", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "打印機(jī)連接成功connect");
        }
    }

    public final synchronized void tryConnect() {
        close();
        boolean hasPrinters = false;
        for (UsbDevice device : mUsbManager.getDeviceList().values()) {
            String name = device.getProductName();
            if (name == null || name.isEmpty()) {
                continue;
            }
            name = name.toLowerCase(Locale.CHINA);
            if (name.contains(PRINTER) || name.contains(MICRO_PRINTER)) {
                hasPrinters = true;
                connect(device);
                break;
            }
        }
        if (!hasPrinters){
            Log.d(TAG, "未搜索到USB打印機(jī)!");
            Toast.makeText(appContext, "未搜索到USB打印機(jī)!", Toast.LENGTH_SHORT).show();
        }
    }

    public final synchronized boolean isHasPermission(UsbDevice dev) {
        return mUsbManager.hasPermission(dev);
    }

    public final synchronized void getPermission(UsbDevice dev) {
        if (!isHasPermission(dev)) {
            PendingIntent pi = PendingIntent.getBroadcast(appContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
            mUsbManager.requestPermission(dev, pi);
            Toast.makeText(appContext, "打印機(jī)請(qǐng)求權(quán)限!", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "打印機(jī)請(qǐng)求權(quán)限r(nóng)equestPermission");
        } else {
            Toast.makeText(appContext, "打印機(jī)連接成功!", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "打印機(jī)連接成功");
        }
    }

    public final synchronized void sendByte(byte[] bits) {
        if (bits == null) {
            return;
        }

        // 打印機(jī)正常
        if (epOut != null && usbIf != null && conn != null) {
            conn.bulkTransfer(epOut, bits, bits.length, 0);
            return;
        }

        Log.d(TAG, "PrinterController sendByte: initDeviceUsb()");
        UsbDeviceConnection tmpConn = initDeviceUsb();
        if (tmpConn != null && tmpConn.claimInterface(usbIf, true)) {
            tmpConn.bulkTransfer(epOut, bits, bits.length, 0);
        }
    }

    public UsbDeviceConnection initDeviceUsb() {
        if (conn == null) {
            conn = mUsbManager.openDevice(dev);
        }

        if (dev == null || dev.getInterfaceCount() == 0) {
            return null;
        }

        usbIf = dev.getInterface(0);
        if (usbIf == null) {
            return null;
        }

        if (usbIf.getEndpointCount() == 0) {
            return null;
        }

        Log.d(TAG, "PrinterController sendByte: i in 0 until it.endpointCount");
        for (int i = 0; i < usbIf.getEndpointCount(); i++) {
            UsbEndpoint endpoint = usbIf.getEndpoint(i);
            if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK && endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                epOut = endpoint;
                break;
            }
        }
        return conn;
    }

    private final synchronized void sendByteDirectly(byte[] bits) {
        UsbDeviceConnection tmpConn = initDeviceUsb();
        if (tmpConn == null) {
            return;
        }
        if (tmpConn.claimInterface(usbIf, true)) { // 獲取USB設(shè)備接口的控制權(quán)
            tmpConn.bulkTransfer(epOut, bits, bits.length, 0);  // 批量數(shù)據(jù)傳輸
        }
    }

    // 讀打印機(jī)狀態(tài), 對(duì)海外打印機(jī)無(wú)用,只對(duì)國(guó)內(nèi)打印機(jī)有用
    // 不能頻繁查詢,會(huì)導(dǎo)致打印機(jī)無(wú)響應(yīng)
    public int readStatus(byte[] command) {
        sendByteDirectly(command);
        int count = (usbIf != null ? usbIf.getEndpointCount() : -1);
        Log.d(TAG, "PrinterController readStatus: " + count);
        if (epIn == null) {
            for (int i = 0; i < count; i++) {
                UsbEndpoint ep = usbIf != null ? usbIf.getEndpoint(i) : null;
                if (ep != null && ep.getType() != UsbConstants.USB_ENDPOINT_XFER_BULK) return -1;
                if (ep != null && ep.getDirection()!= UsbConstants.USB_DIR_IN) continue;    //不是讀端就跳過(guò),一共2個(gè)端口,一個(gè)讀一個(gè)寫(xiě)
                //讀端初始化
                if (epIn == null) {
                    epIn = ep;
                    Log.d(TAG, "PrinterController read:epIn init");
                }
                break;
            }
        }

        UsbEndpoint tmpEpIn = epIn;
        UsbDeviceConnection tmpConn = conn;
        if (tmpEpIn == null || tmpConn == null) return -1;

        byte[] retData = new byte[64];
        int readLen = tmpConn.bulkTransfer(tmpEpIn, retData, retData.length, 3000);
        Log.d(TAG, "PrinterController read:readLen " + readLen);

        if (readLen == -1) return -1;
        Log.d(TAG, "PrinterController read:retData != -1");

        byte[] realData = new byte[65];
        System.arraycopy(retData, 0, realData, 0, retData.length);
        Log.d(TAG, "PrinterController read:readLen " + realData[0]);

        return realData[0];
    }

    // 一行打印2段內(nèi)容
    public String printTwoData(String leftText, String rightText) {

        int leftTextLength = leftText.getBytes().length;
        int rightTextLength = rightText.getBytes().length;

        StringBuilder sb = new StringBuilder();
        sb.append(leftText);

        // 計(jì)算兩側(cè)文字中間的空格
        int marginBetweenMiddleAndRight = LINE_BYTE_SIZE - leftTextLength - rightTextLength;
        for (int i = 0; i < marginBetweenMiddleAndRight; i++) {
            sb.append(" ");
        }
        sb.append(rightText);

        // 處理信息過(guò)長(zhǎng)問(wèn)題
        int outCome = (leftTextLength + rightTextLength) / LINE_BYTE_SIZE;  // 結(jié)果
        int remainder = (leftTextLength + rightTextLength) % LINE_BYTE_SIZE;// 余數(shù)
        // 結(jié)果不為0并且還有余數(shù),表明換行了,此時(shí)需要在后面加空白
        // 計(jì)算出離右邊的距離
        int marginRightBlank = (outCome > 0 && remainder > 0) ? (((outCome + 1) * LINE_BYTE_SIZE) - leftTextLength - rightTextLength) : 0;
        for (int i = 0; i < marginRightBlank; i++) {
            sb.append(" ");
        }
        return sb.toString();
    }

    // 一行打印3段內(nèi)容
    public String printThreeData(String leftText, String centerText, String rightText) {

        int leftTextLength = leftText.getBytes().length;
        int centerTextLength = centerText.getBytes().length;
        int rightTextLength = rightText.getBytes().length;

        StringBuilder sb = new StringBuilder();
        sb.append(leftText);

        // 計(jì)算兩側(cè)文字中間的空格
        int marginBetweenMiddleAndRight = LINE_BYTE_SIZE - leftTextLength - centerTextLength - rightTextLength;
        for (int i = 0; i < marginBetweenMiddleAndRight/2; i++) {
            sb.append(" ");
        }
        sb.append(centerText);

        for (int i = 0; i < marginBetweenMiddleAndRight/2; i++) {
            sb.append(" ");
        }
        sb.append(rightText);

        // 處理信息過(guò)長(zhǎng)問(wèn)題
        int outCome = (leftTextLength + centerTextLength + rightTextLength) / LINE_BYTE_SIZE;  // 結(jié)果
        int remainder = (leftTextLength + centerTextLength + rightTextLength) % LINE_BYTE_SIZE;// 余數(shù)
        // 結(jié)果不為0并且還有余數(shù),表明換行了,此時(shí)需要在后面加空白
        // 計(jì)算出離右邊的距離
        int marginRightBlank = (outCome > 0 && remainder > 0) ? (((outCome + 1) * LINE_BYTE_SIZE) - leftTextLength - centerTextLength - rightTextLength) : 0;
        for (int i = 0; i < marginRightBlank; i++) {
            sb.append(" ");
        }
        return sb.toString();
    }

    public static String date2String(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public final synchronized void close() {
        if (conn != null) {
            conn.close();
            epOut = null;
            epIn = null;
            usbIf = null;
            conn = null;
            dev = null;
        }
    }

    // 監(jiān)聽(tīng)usb設(shè)備連接狀態(tài)廣播,
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive intent = " + intent);
        // USB設(shè)備斷開(kāi)廣播
        if (intent.getAction() == UsbManager.ACTION_USB_DEVICE_DETACHED){
            Toast.makeText(appContext, "打印機(jī)連接斷開(kāi)", Toast.LENGTH_SHORT).show();
        }
    }

}

5. 打印機(jī)使用

添加好打印工具類(lèi)后就可以再M(fèi)ainActivity中連接、使用打印機(jī)了。MainActivity中添加了兩個(gè)按鈕,分別用于實(shí)現(xiàn)連接打印機(jī)和開(kāi)始打印2個(gè)功能。

<MainActivity.java>

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "PrintingActivity";

    private PrinterController printer;
    private final PrinterCommand commands = new PrinterCommand();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化打印工具類(lèi)
        printer = PrinterController.getInstance();
        printer.getPrinterContext(getApplicationContext());

        // 動(dòng)態(tài)注冊(cè) usb設(shè)備斷開(kāi) 廣播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(printer, intentFilter);

        initView();
    }

    private void initView(){
        // 連接打印機(jī)
        findViewById(R.id.connect_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                initPrint();
            }
        });
        // 開(kāi)始打印
        findViewById(R.id.print_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startPrinting();
            }
        });

    }

    // 連接打印機(jī)
    private void initPrint(){
        printer.close();
        printer.tryConnect();
    }

    // 開(kāi)始打印
    private void startPrinting(){
        // 1. 打印之前先建立連接
        printer.tryConnect();

        // 2. 檢查狀態(tài)是否正常
        int status = printer.readStatus(Command.DLE_eot4);
        if (status != 18){
            Toast.makeText(this, "打印機(jī)異常,請(qǐng)檢查打印機(jī)!", Toast.LENGTH_SHORT).show();
            Log.e(TAG,"printer error : status = " + status);
            return;
        }else {
            Toast.makeText(this, "打印機(jī)正常!", Toast.LENGTH_SHORT).show();
            Log.e(TAG,"printer over : status = " + status);
        }

        // 3. 自定義打印內(nèi)容
        customPrint();

        // 4. 關(guān)閉打印機(jī)
        printer.close();
    }

    /**
     * 自定義打印格式和打印內(nèi)容
     */
    private void customPrint(){
        printOneData("北京稻香村", 1, false, true, "all", 2, true, 2);
        printTwoData("打印時(shí)間:", printer.date2String(new Date(), printer.FMT_YYYY_MM_DD_HH_MM2), 1, false, true, "all", 1, true, 1);
        printOneData("-----------------------------------------------", 1, false, false, "", 0, true, 1);
        printThreeData("單價(jià)", "數(shù)量", "金額", 1, false, false, "", 0, true, 1);
        printOneData("-----------------------------------------------", 1, false, false, "", 0, true, 1);
        printThreeData("蛋黃酥", "1", "¥50.00", 1, false, false, "", 0, true, 1);
        printOneData("-----------------------------------------------", 1, false, false, "", 0, true, 1);
        printTwoData("實(shí)收金額", "¥50.00", 1, true, false, "", 0, true, 4);
    }

    /**
     * 設(shè)置打印內(nèi)容:一行只有1個(gè)打印內(nèi)容
     * @param text 打印的文本
     * @param align 對(duì)齊模式       0#左對(duì)齊, 1#居中, 2#右對(duì)齊
     * @param isBold 是否加粗
     * @param isEnlarge 是否放大
     * @param direction 放大方向    horizontal#水平放大, vertical#垂直放大, all#整體放大
     * @param multiple 放大倍數(shù)     [0,7]
     * @param isEnter 是否回車(chē)
     * @param enterLine 換行數(shù)     [1.10]
     */
    private void printOneData(String text, int align, boolean isBold, boolean isEnlarge, String direction, int multiple, boolean isEnter, int enterLine){

        printer.sendByte(commands.POS_Set_PrtInit());   // 初始化格式
        printer.sendByte(commands.POS_S_Align(align));  // 對(duì)齊模式
        if (isBold){
            printer.sendByte(commands.Set_Bold());      //加粗
        }
        if (isEnlarge){
            if ("horizontal".equals(direction)){
                printer.sendByte(commands.POS_S_GS_H(multiple));   // 橫向放大
            }else if ("vertical".equals(direction)){
                printer.sendByte(commands.POS_S_GS_O(multiple));   // 縱向放大
            }else if ("all".equals(direction)){
                printer.sendByte(commands.POS_S_GS_O_H(multiple)); // 放大字體
            }
        }
        printer.sendByte(text.getBytes(Charset.forName("GBK")));  // 設(shè)置打印內(nèi)容
//        printer.sendByte(commands.POS_Set_Enter());  // 回車(chē)
        if (isEnter) {
            printer.sendByte(commands.POS_S_PrintLine(enterLine));  // 換行
        }
    }

    /**
     * 設(shè)置打印內(nèi)容:一行有2個(gè)打印內(nèi)容
     * @param leftText 左側(cè)打印的文本
     * @param rightText 右側(cè)打印的文本
     * @param align 對(duì)齊模式       0#左對(duì)齊, 1#居中, 2#右對(duì)齊
     * @param isBold 是否加粗
     * @param isEnlarge 是否放大
     * @param direction 放大方向    horizontal#水平放大, vertical#垂直放大, all#整體放大
     * @param multiple 放大倍數(shù)     [0,7]
     * @param isEnter 是否回車(chē)
     * @param enterLine 換行數(shù)     [1.10]
     */
    private void printTwoData(String leftText, String rightText, int align, boolean isBold, boolean isEnlarge, String direction, int multiple, boolean isEnter, int enterLine){

        printer.sendByte(commands.POS_Set_PrtInit());   // 初始化格式
        printer.sendByte(commands.POS_S_Align(align));  // 對(duì)齊模式
        if (isBold){
            printer.sendByte(commands.Set_Bold());      //加粗
        }
        if (isEnlarge){
            if ("horizontal".equals(direction)){
                printer.sendByte(commands.POS_S_GS_H(multiple));   // 橫向放大
            }else if ("vertical".equals(direction)){
                printer.sendByte(commands.POS_S_GS_O(multiple));   // 縱向放大
            }else if ("all".equals(direction)){
                printer.sendByte(commands.POS_S_GS_O_H(multiple)); // 放大字體
            }
        }
        printer.sendByte(printer.printTwoData(leftText, rightText).getBytes(Charset.forName("GBK")));  // 設(shè)置打印內(nèi)容
        if (isEnter) {
            printer.sendByte(commands.POS_S_PrintLine(enterLine));  // 換行
        }
    }

    /**
     * 設(shè)置打印內(nèi)容:一行有3個(gè)打印內(nèi)容
     * @param leftText 左側(cè)打印的文本
     * @param centerText 中間打印的文本
     * @param rightText 右側(cè)打印的文本
     * @param align 對(duì)齊模式       0#左對(duì)齊, 1#居中, 2#右對(duì)齊
     * @param isBold 是否加粗
     * @param isEnlarge 是否放大
     * @param direction 放大方向    horizontal#水平放大, vertical#垂直放大, all#整體放大
     * @param multiple 放大倍數(shù)     [0,7]
     * @param isEnter 是否回車(chē)
     * @param enterLine 換行數(shù)     [1.10]
     */
    private void printThreeData(String leftText, String centerText, String rightText, int align, boolean isBold, boolean isEnlarge, String direction, int multiple, boolean isEnter, int enterLine){

        printer.sendByte(commands.POS_Set_PrtInit());   // 初始化格式
        printer.sendByte(commands.POS_S_Align(align));  // 對(duì)齊模式
        if (isBold){
            printer.sendByte(commands.Set_Bold());      //加粗
        }
        if (isEnlarge){
            if ("horizontal".equals(direction)){
                printer.sendByte(commands.POS_S_GS_H(multiple));   // 橫向放大
            }else if ("vertical".equals(direction)){
                printer.sendByte(commands.POS_S_GS_O(multiple));   // 縱向放大
            }else if ("all".equals(direction)){
                printer.sendByte(commands.POS_S_GS_O_H(multiple)); // 放大字體
            }
        }
        printer.sendByte(printer.printThreeData(leftText, centerText, rightText).getBytes(Charset.forName("GBK")));  // 設(shè)置打印內(nèi)容
        if (isEnter) {
            printer.sendByte(commands.POS_S_PrintLine(enterLine));  // 換行
        }
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,463評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,009評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,218評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,436評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,659評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,917評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,687評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容