Android 蓝牙小票打印机功能

记录下最近项目开发中使用到的蓝牙打印机功能

    /**
     * 从已配对设配中,删选出某一特定类型的设备展示
     *
     * @param deviceClass
     * @return
     */
    public static List<BluetoothDevice> getSpecificDevice(int deviceClass) {
        List<BluetoothDevice> devices = BluetoothUtil.getPairedDevices();
        List<BluetoothDevice> printerDevices = new ArrayList<>();

        for (BluetoothDevice device : devices) {
            @SuppressLint("MissingPermission") BluetoothClass klass = device.getBluetoothClass();
            // 关于蓝牙设备分类参考 http://stackoverflow.com/q/23273355/4242112
            if (klass.getMajorDeviceClass() == deviceClass)
                printerDevices.add(device);
        }

        return printerDevices;
    }

    /**
     * 获取所有已配对的设备
     */
    @SuppressLint("MissingPermission")
    public static List<BluetoothDevice> getPairedDevices() {
        List deviceList = new ArrayList<>();
        if (BluetoothAdapter.getDefaultAdapter() != null && BluetoothAdapter.getDefaultAdapter().getBondedDevices() != null) {
            Set<BluetoothDevice> pairedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
            if (pairedDevices.size() > 0) {
                for (BluetoothDevice device : pairedDevices) {
                    deviceList.add(device);
                }
            }
        }
        return deviceList;
    }

    public void connectDevice(BluetoothDevice device, int taskType) {
        if (checkBluetoothState() && device != null) {
            mConnectTask = new ConnectBluetoothTask(taskType).execute(device);
        }
    }

   class ConnectBluetoothTask extends AsyncTask<BluetoothDevice, Integer, BluetoothSocket> {

        int mTaskType;

        public ConnectBluetoothTask(int taskType) {
            this.mTaskType = taskType;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected BluetoothSocket doInBackground(BluetoothDevice... params) {

            try {
                if (mSocket != null) {
                    mSocket.close();
                }
                mSocket = BluetoothUtil.connectDevice(params[0]);
                return mSocket;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(BluetoothSocket socket) {
            checkSocket(socket);
            super.onPostExecute(socket);
        }
    }

    private void checkSocket(BluetoothSocket socket) {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (socket == null || !socket.isConnected()) {
                    LogUtils.v(TAG, "连接打印机失败");
                    connectDevice(selectDevice, 2);
                } else {
                    LogUtils.v(TAG, "连接打印机成功");
                    loadingDialog = LoadingUtils.showLoadingText(SalesBillingOrderActivity.this, ConstantValue.PRINT_TEXT);
                    printData(socket);
                }
            }
        }, 200);
    }

 public void printData(BluetoothSocket bluetoothSocket) {
        try {
            PrintUtil pUtil = new PrintUtil(bluetoothSocket.getOutputStream(), "GBK");
            // 店铺名 居中 放大
            pUtil.printAlignment(1);
            if (!TextUtils.isEmpty(printUserBean.getData().getBossmanName())) {
                pUtil.printLargeText(printUserBean.getData().getBossmanName() + "销售单");
                pUtil.printLine(2);
            }
            pUtil.printAlignment(0);
            pUtil.printText("客户: " + getIntent().getStringExtra(ConstantValue.NAME));
            pUtil.printLine();
            pUtil.printAlignment(0);
            pUtil.printText("日期: " + TimeSelectUtils.getFormatTime(new Date()));
            pUtil.printLine();
            // 分隔线
            pUtil.printDashLine();
            pUtil.printLine();
            if (productlistBeansList != null && productlistBeansList.size() > 0) {
                for (int i = 0; i < productlistBeansList.size(); i++) {
                    pUtil.printAlignment(0);
                    pUtil.printText((i + 1) + " " + productlistBeansList.get(i).getProductName());
                    pUtil.printLine();
                    pUtil.printAlignment(0);
                    pUtil.printText(productlistBeansList.get(i).getSpecifications() + "  " + productlistBeansList.get(i).getBarCode());
                    pUtil.printLine();
                    if (productlistBeansList.get(i).isZpFlag()) {
                        pUtil.printThreeColumn(productlistBeansList.get(i).getLevelPrice() + "元", "x" + productlistBeansList.get(i).getSelectNum() + productlistBeansList.get(i).getUnitName(), "赠品");
                    } else {
                        pUtil.printThreeColumn(productlistBeansList.get(i).getLevelPrice() + "元", "x" + productlistBeansList.get(i).getSelectNum() + productlistBeansList.get(i).getUnitName(), Float.parseFloat(productlistBeansList.get(i).getLevelPrice()) * Float.parseFloat(productlistBeansList.get(i).getSelectNum()) + "元");
                    }
                    pUtil.printLine(1);
                }
            }
            pUtil.printLine();
            pUtil.printAlignment(2);
            pUtil.printText("合计金额:" + mTvTotalPrice.getText().toString().trim() + "元");
            pUtil.printLine();
            //添加费用支出
            if (mCheckBox.isChecked()) {
                pUtil.printText("费用名称:" + selectValue);
                pUtil.printLine();
                pUtil.printText("费用金额:" + mEtFyje.getText().toString().trim() + "元");
                pUtil.printLine();
                pUtil.printText("费用说明:" + mEtFysm.getText().toString().trim());
                pUtil.printLine();
                pUtil.printText("应收金额:" + mTvYsje.getText().toString().trim() + "元");
                pUtil.printLine();
            }
            //
            pUtil.printDashLine();
            pUtil.printLine(1);
            pUtil.printAlignment(0);
            pUtil.printText("备注: ");
            pUtil.printLine(3);
            pUtil.printDashLine();
            pUtil.printLine();
            if (!TextUtils.isEmpty(printUserBean.getData().getSalesmanName())) {
                saleName = printUserBean.getData().getSalesmanName();
            } else {
                saleName = "";
            }
            if (!TextUtils.isEmpty(printUserBean.getData().getSalesmanTel())) {
                saleTel = printUserBean.getData().getSalesmanTel();
            } else {
                saleTel = "";
            }
            pUtil.printAlignment(0);
            pUtil.printText("业务员: " + saleName + "  " + saleTel);
            pUtil.printLine();
            if (!TextUtils.isEmpty(printUserBean.getData().getBossmanTel1())) {
                bossTelOne = printUserBean.getData().getBossmanTel1();
            } else {
                bossTelOne = "";
            }
            if (!TextUtils.isEmpty(printUserBean.getData().getBossmanTel2())) {
                bossTelTwo = printUserBean.getData().getBossmanTel2();
            } else {
                bossTelTwo = "";
            }
            pUtil.printAlignment(0);
            pUtil.printText("公司电话: " + bossTelOne + "  " + bossTelTwo);
            pUtil.printLine();
            if (!TextUtils.isEmpty(printUserBean.getData().getBossmanLoc())) {
                bossLoc = printUserBean.getData().getBossmanLoc();
            } else {
                bossLoc = "";
            }
            pUtil.printAlignment(0);
            pUtil.printText("公司地址: " + bossLoc);
            pUtil.printLine(1);

            if (!TextUtils.isEmpty(printUserBean.getData().getTailContent())) {
                pUtil.printAlignment(0);
                pUtil.printText(printUserBean.getData().getTailContent());
                pUtil.printLine(3);
            }

            LoadingUtils.hideLoadingDelay(loadingDialog);
        } catch (IOException e) {
            e.printStackTrace();
            ToastUtils.showShort("打印失败");
        }
    }

/**
 * 蓝牙打印工具类
 */
public class PrintUtil {

    private OutputStreamWriter mWriter = null;
    private OutputStream mOutputStream = null;

    //    public final static int WIDTH_PIXEL = 550;
    public final static int WIDTH_PIXEL = 458;
    public final static int IMAGE_SIZE = 320;

    /**
     * 初始化Pos实例
     *
     * @param encoding 编码
     * @throws IOException
     */
    public PrintUtil(OutputStream outputStream, String encoding) throws IOException {
        mWriter = new OutputStreamWriter(outputStream, encoding);
        mOutputStream = outputStream;
        initPrinter();
    }

    public void print(byte[] bs) throws IOException {
        mOutputStream.write(bs);
    }

    public void printRawBytes(byte[] bytes) throws IOException {
        mOutputStream.write(bytes);
        mOutputStream.flush();
    }

    /**
     * 初始化打印机
     *
     * @throws IOException
     */
    public void initPrinter() throws IOException {
        mWriter.write(0x1B);
        mWriter.write(0x40);
        mWriter.flush();
    }

    /**
     * 打印换行
     *
     * @return length 需要打印的空行数
     * @throws IOException
     */
    public void printLine(int lineNum) throws IOException {
        for (int i = 0; i < lineNum; i++) {
            mWriter.write("\n");
        }
        mWriter.flush();
    }

    /**
     * 打印换行(只换一行)
     *
     * @throws IOException
     */
    public void printLine() throws IOException {
        printLine(1);
    }

    /**
     * 打印空白(一个Tab的位置,约4个汉字)
     *
     * @param length 需要打印空白的长度,
     * @throws IOException
     */
    public void printTabSpace(int length) throws IOException {
        for (int i = 0; i < length; i++) {
            mWriter.write("\t");
        }
        mWriter.flush();
    }

    /**
     * 绝对打印位置
     *
     * @return
     * @throws IOException
     */
    public byte[] setLocation(int offset) throws IOException {
        byte[] bs = new byte[4];
        bs[0] = 0x1B;
        bs[1] = 0x24;
        bs[2] = (byte) (offset % 256);
        bs[3] = (byte) (offset / 256);
        return bs;
    }

    public byte[] getGbk(String stText) throws IOException {
        byte[] returnText = stText.getBytes("GBK"); // 必须放在try内才可以
        return returnText;
    }

    private int getStringPixLength(String str) {
        int pixLength = 0;
        char c;
        for (int i = 0; i < str.length(); i++) {
            c = str.charAt(i);
            if (Pinyin.isChinese(c)) {
                pixLength += 24;
            } else {
                pixLength += 12;
            }
        }
        return pixLength;
    }

    public int getOffset(String str) {
        return WIDTH_PIXEL - getStringPixLength(str);
    }

    /**
     * 打印文字
     *
     * @param text
     * @throws IOException
     */
    public void printText(String text) throws IOException {
        mWriter.write(text);
        mWriter.flush();
    }

    /**
     * 对齐0:左对齐,1:居中,2:右对齐
     */
    public void printAlignment(int alignment) throws IOException {
        mWriter.write(0x1b);
        mWriter.write(0x61);
        mWriter.write(alignment);
    }

    public void printLargeText(String text) throws IOException {

        mWriter.write(0x1b);
        mWriter.write(0x21);
//        mWriter.write(0x30);
        mWriter.write(48);

        mWriter.write(text);

        mWriter.write(0x1b);
        mWriter.write(0x21);
        mWriter.write(0);

        mWriter.flush();
    }

    public void printTwoColumn(String title, String content) throws IOException {
        int iNum = 0;
        byte[] byteBuffer = new byte[100];
        byte[] tmp;

        tmp = getGbk(title);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = setLocation(getOffset(content));
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = getGbk(content);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);

        print(byteBuffer);
    }

    public void printThreeColumn(String left, String middle, String right) throws IOException {
        int iNum = 0;
        byte[] byteBuffer = new byte[200];
        byte[] tmp = new byte[0];

        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = getGbk(left);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        int pixLength = getStringPixLength(left) % WIDTH_PIXEL;
        if (pixLength > WIDTH_PIXEL / 2 || pixLength == 0) {
            middle = "\n\t\t" + middle;
        }

        tmp = setLocation(205);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = getGbk(middle);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = setLocation(getOffset(right));
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);
        iNum += tmp.length;

        tmp = getGbk(right);
        System.arraycopy(tmp, 0, byteBuffer, iNum, tmp.length);

        print(byteBuffer);
    }

 

    public void printDashLine() throws IOException {
        printText("-------------------------------------");
    }

    public void printBitmap(Bitmap bmp) throws IOException {
        bmp = compressPic(bmp);
        byte[] bmpByteArray = draw2PxPoint(bmp);
        printRawBytes(bmpByteArray);
    }

    /*************************************************************************
     * 假设一个360*360的图片,分辨率设为24, 共分15行打印 每一行,是一个 360 * 24 的点阵,y轴有24个点,存储在3个byte里面。
     * 即每个byte存储8个像素点信息。因为只有黑白两色,所以对应为1的位是黑色,对应为0的位是白色
     **************************************************************************/
    private byte[] draw2PxPoint(Bitmap bmp) {
        //先设置一个足够大的size,最后在用数组拷贝复制到一个精确大小的byte数组中
        int size = bmp.getWidth() * bmp.getHeight() / 8 + 1000;
        byte[] tmp = new byte[size];
        int k = 0;
        // 设置行距为0
        tmp[k++] = 0x1B;
        tmp[k++] = 0x33;
        tmp[k++] = 0x00;
        // 居中打印
        tmp[k++] = 0x1B;
        tmp[k++] = 0x61;
        tmp[k++] = 1;
        for (int j = 0; j < bmp.getHeight() / 24f; j++) {
            tmp[k++] = 0x1B;
            tmp[k++] = 0x2A;// 0x1B 2A 表示图片打印指令
            tmp[k++] = 33; // m=33时,选择24点密度打印
            tmp[k++] = (byte) (bmp.getWidth() % 256); // nL
            tmp[k++] = (byte) (bmp.getWidth() / 256); // nH
            for (int i = 0; i < bmp.getWidth(); i++) {
                for (int m = 0; m < 3; m++) {
                    for (int n = 0; n < 8; n++) {
                        byte b = px2Byte(i, j * 24 + m * 8 + n, bmp);
                        tmp[k] += tmp[k] + b;
                    }
                    k++;
                }
            }
            tmp[k++] = 10;// 换行
        }
        // 恢复默认行距
        tmp[k++] = 0x1B;
        tmp[k++] = 0x32;

        byte[] result = new byte[k];
        System.arraycopy(tmp, 0, result, 0, k);
        return result;
    }

    /**
     * 图片二值化,黑色是1,白色是0
     *
     * @param x   横坐标
     * @param y   纵坐标
     * @param bit 位图
     * @return
     */
    private byte px2Byte(int x, int y, Bitmap bit) {
        if (x < bit.getWidth() && y < bit.getHeight()) {
            byte b;
            int pixel = bit.getPixel(x, y);
            int red = (pixel & 0x00ff0000) >> 16; // 取高两位
            int green = (pixel & 0x0000ff00) >> 8; // 取中两位
            int blue = pixel & 0x000000ff; // 取低两位
            int gray = RGB2Gray(red, green, blue);
            if (gray < 128) {
                b = 1;
            } else {
                b = 0;
            }
            return b;
        }
        return 0;
    }

    /**
     * 图片灰度的转化
     */
    private int RGB2Gray(int r, int g, int b) {
        int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b); // 灰度转化公式
        return gray;
    }

    /**
     * 对图片进行压缩(去除透明度)
     *
     * @param bitmapOrg
     */
    private Bitmap compressPic(Bitmap bitmapOrg) {
        // 获取这个图片的宽和高
        int width = bitmapOrg.getWidth();
        int height = bitmapOrg.getHeight();
        // 定义预转换成的图片的宽度和高度
        int newWidth = IMAGE_SIZE;
        int newHeight = IMAGE_SIZE;
        Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
        Canvas targetCanvas = new Canvas(targetBmp);
        targetCanvas.drawColor(0xffffffff);
        targetCanvas.drawBitmap(bitmapOrg, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);
        return targetBmp;
    }

}

以上是蓝牙打印小票的记录。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值