Android 蓝牙打印小票与WiFi打印小票两种打印方式的实现(带有图片和二维码)

时间:2024-03-28 15:39:31

转载至: https://blog.csdn.net/u011056653/article/details/74308254

最近在做小票打印这块,项目需求是蓝牙和WiFi两种都要实现,开始做的时候也是一脸懵,然后网上找了一些代码,看了好多博主的文章,最后自己把这些都综合到一起0.0,结果还好成功了

先看看图吧,蓝牙和WiFi打印出的都是一样的,毕竟都是同一个工具类(打印机型号  爱宝POS-80C 、 资江 ZJ-80)

Android 蓝牙打印小票与WiFi打印小票两种打印方式的实现(带有图片和二维码)

先来看看WiFi打印(旁边的色块是打印纸自带的,我也很无奈)

首先在你的activity里触发点击事件

right = (TextView) findViewById(R.id.right);//点击WiFi打印
right.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        pos();
    }
});

//调用打印的方法

    private void pos() {
        // 开启一个子线程
        new Thread() {
            public void run() {
                try {              //打印机网口IP    打印机端口号     编码方式
                    pos = new Pos(Preference.instance(PayTypeActivity.this).getIPAddress(), Integer.parseInt(Preference.instance(PayTypeActivity.this).getPost_IDs()), "gbk");
                    //初始化打印机
                    pos.initPos();
                    if (!TextUtils.isEmpty(objBean.getHead_img())){
                        pos.printLocation(1);
                        bitmap = pos.compressPic(returnBitMap(objBean.getHead_img()));
                        pos.draw2PxPoint(bitmap);
                    }
                    pos.printLocation(1);
                    pos.bold(true);
                    pos.printTabSpace(2);
                    pos.printWordSpace(1);
                    pos.printTextNewLine(objBean.getShop_name());

                    pos.printLocation(0);
                    pos.printTextNewLine("----------------------------------------------");
                    pos.bold(false);
                    pos.printTextNewLine("订 单 号:"+objBean.getSn());
                    pos.printTextNewLine("用 户 名:"+objBean.getMember());
                    pos.printTextNewLine("订单日期:"+objBean.getCreate_time());
                    pos.printTextNewLine("支付方式:"+objBean.getPay_way());
                    pos.printTextNewLine("订单折扣:"+objBean.getDiscount());
                    pos.printTextNewLine("订单备注:"+objBean.getRemarks());
                    pos.printLine(2);

                    pos.printText("货号          尺码    颜色    数量   小计");
                    pos.printLocation(20, 1);
                    pos.printTextNewLine("----------------------------------------------");

                    for (ParentBean foods : foodsBean) {
                        pos.printTextNewLine(foods.getGoods_name()+"          "+foods.getCode_number()+"     "+foods.getColour()+"      "+foods.getNum()+"      "+foods.getPay_back());
                        pos.printLocation(20, 1);
                    }

                    pos.printTextNewLine("----------------------------------------------");
                    pos.printLocation(0);
                    pos.printLine(1);
                    pos.printTextNewLine("订单总数:"+objBean.getNums());
                    pos.printTextNewLine("应收金额:"+objBean.getActual_pay());
                    pos.printTextNewLine("优惠金额:"+objBean.getDiscount_pay());
                    pos.printTextNewLine("实收金额:"+objBean.getPay());
                    pos.printLine(2);

//                    //打印二维码  -- 如果提供了二维码的地址则用该方法
//                    pos.qrCode(objBean.getQr_code());

                    //打印二维码的图片 -- 如果提供了二维码的截图则用该方法
                    if (!TextUtils.isEmpty(objBean.getQr_code())){
                        pos.printLocation(1);
                        Qbitmap = pos.compressPic(returnBitMap(objBean.getQr_code()));//url 转换为bitmap
                        pos.draw2PxPoint(Qbitmap);
                    }
                    //切纸
                    pos.feedAndCut();
                    pos.closeIOAndSocket();
                    pos = null;
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                    showToast(e.toString());
                    Log.d("tag", "错误信息1:" + e.toString());
                } catch (IOException e) {
                    e.printStackTrace();
                    showToast(e.toString());
                    Log.d("tag", "错误信息2:" + e.toString());
                }
            }

        }.start();

    }

//将图片url转换为bitmap

    public Bitmap returnBitMap(String url) {
        URL myFileUrl = null;
        Bitmap bitmap = null;
        try {
            myFileUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }
再来看看调用的工具类(蓝牙和WiFi共用一个,只是初始化方式不同)

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Pos {
    //定义编码方式
    private static String encoding = null;

    private Socket sock = null;
    // 通过socket流进行读写
    private OutputStream socketOut = null;
    private OutputStreamWriter writer = null;

    /**
     * 初始化Pos实例
     *
     * @param ip 打印机IP
     * @param port 打印机端口号
     * @param encoding 编码
     * @throws IOException
     */
    public Pos(String ip, int port, String encoding) throws IOException {
        sock = new Socket(ip, port);
        socketOut = new DataOutputStream(sock.getOutputStream());
        this.encoding = encoding;
        writer = new OutputStreamWriter(socketOut, encoding);
    }

    //蓝牙初始化
    public Pos(OutputStream outputStream, String encoding) throws IOException {
        writer = new OutputStreamWriter(outputStream, encoding);
        socketOut = outputStream;
        initPrinter();
    }

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

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

    /**
     * 初始化打印机
     *
     * @throws IOException
     */
    public void initPrinter() throws IOException {
        socketOut.write(0x1B);
        socketOut.write(0x40);
        socketOut.flush();
    }
    /**
     * 关闭IO流和Socket
     *
     * @throws IOException
     */
    public void closeIOAndSocket() throws IOException {
        writer.close();
        socketOut.close();
        sock.close();
    }

    /**
     * 打印二维码
     *
     * @param qrData 二维码的内容
     * @throws IOException
     */
    public void qrCode(String qrData) throws IOException {
        int moduleSize = 8;
        int length = qrData.getBytes(encoding).length;

        //打印二维码矩阵
        writer.write(0x1D);// init
        writer.write("(k");// adjust height of barcode
        writer.write(length + 3); // pl
        writer.write(0); // ph
        writer.write(49); // cn
        writer.write(80); // fn
        writer.write(48); //
        writer.write(qrData);

        writer.write(0x1D);
        writer.write("(k");
        writer.write(3);
        writer.write(0);
        writer.write(49);
        writer.write(69);
        writer.write(48);

        writer.write(0x1D);
        writer.write("(k");
        writer.write(3);
        writer.write(0);
        writer.write(49);
        writer.write(67);
        writer.write(moduleSize);

        writer.write(0x1D);
        writer.write("(k");
        writer.write(3); // pl
        writer.write(0); // ph
        writer.write(49); // cn
        writer.write(81); // fn
        writer.write(48); // m

        writer.flush();

    }

    /**
     * 进纸并全部切割
     *
     * @return
     * @throws IOException
     */
    public void feedAndCut() throws IOException {
        writer.write(0x1D);
        writer.write(86);
        writer.write(65);
        //    writer.write(0);
        //切纸前走纸多少
        writer.write(100);
        writer.flush();

        //另外一种切纸的方式
        //    byte[] bytes = {29, 86, 0};
        //    socketOut.write(bytes);
    }

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

    /**
     * 打印换行(只换一行)
     *
     * @throws IOException
     */
    protected void printLine() throws IOException {
        writer.write("\n");
        writer.flush();
    }

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

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

    /**
     * 打印位置调整
     *
     * @param position 打印位置 0:居左(默认) 1:居中 2:居右
     * @throws IOException
     */
    public void printLocation(int position) throws IOException {
        writer.write(0x1B);
        writer.write(97);
        writer.write(position);
        writer.flush();
    }

    /**
     * 绝对打印位置
     *
     * @throws IOException
     */
    public void printLocation(int light, int weight) throws IOException {
        writer.write(0x1B);
        writer.write(0x24);
        writer.write(light);
        writer.write(weight);
        writer.flush();
    }

    /**
     * 打印文字
     *
     * @param text
     * @throws IOException
     */
    public void printText(String text) throws IOException {
        String s = text;
        byte[] content = s.getBytes("gbk");
        socketOut.write(content);
        socketOut.flush();
    }

    /**
     * 新起一行,打印文字
     *
     * @param text
     * @throws IOException
     */
    public void printTextNewLine(String text) throws IOException {
        //换行
        writer.write("\n");
        writer.flush();

        String s = text;
        byte[] content = s.getBytes("gbk");
        socketOut.write(content);
        socketOut.flush();
    }

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

    /**
     * 加粗
     *
     * @param flag false为不加粗
     * @return
     * @throws IOException
     */
    public void bold(boolean flag) throws IOException {
        if (flag) {
            //常规粗细
            writer.write(0x1B);
            writer.write(69);
            writer.write(0xF);
            writer.flush();
        } else {
            //加粗
            writer.write(0x1B);
            writer.write(69);
            writer.write(0);
            writer.flush();
        }
    }

    /**
     * 对图片进行压缩(去除透明度)
     *
     * @param
     */
    public static Bitmap compressPic(Bitmap bitmap) {
        // 获取这个图片的宽和高
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        // 指定调整后的宽度和高度
        int newWidth = 200;
        int newHeight = 200;
        Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
        Canvas targetCanvas = new Canvas(targetBmp);
        targetCanvas.drawColor(0xffffffff);
        targetCanvas.drawBitmap(bitmap, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);
        return targetBmp;
    }

    /**
     * 灰度图片黑白化,黑色是1,白色是0
     *
     * @param x   横坐标
     * @param y   纵坐标
     * @param bit 位图
     * @return
     */
    public static 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 static int RGB2Gray(int r, int g, int b) {
        int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b);  //灰度转化公式
        return gray;
    }

    /*************************************************************************
     * 假设一个240*240的图片,分辨率设为24, 共分10行打印
     * 每一行,是一个 240*24 的点阵, 每一列有24个点,存储在3个byte里面。
     * 每个byte存储8个像素点信息。因为只有黑白两色,所以对应为1的位是黑色,对应为0的位是白色
     **************************************************************************/
    /**
     * 把一张Bitmap图片转化为打印机可以打印的字节流
     *
     * @param bmp
     * @return
     */
    public void draw2PxPoint(Bitmap bmp) throws IOException {

        //用来存储转换后的 bitmap 数据。为什么要再加1000,这是为了应对当图片高度无法
        //整除24时的情况。比如bitmap 分辨率为 240 * 250,占用 7500 byte,
        //但是实际上要存储11行数据,每一行需要 24 * 240 / 8 =720byte 的空间。再加上一些指令存储的开销,
        //所以多申请 1000byte 的空间是稳妥的,不然运行时会抛出数组访问越界的异常。
        int size = bmp.getWidth() * bmp.getHeight() / 8 + 1000;
        byte[] data = new byte[size];
        int k = 0;
        //设置行距为0的指令
        data[k++] = 0x1B;
        data[k++] = 0x33;
        data[k++] = 0x00;
        // 逐行打印
        for (int j = 0; j < bmp.getHeight() / 24f; j++) {
            //打印图片的指令
            data[k++] = 0x1B;
            data[k++] = 0x2A;
            data[k++] = 33;
            data[k++] = (byte) (bmp.getWidth() % 256); //nL
            data[k++] = (byte) (bmp.getWidth() / 256); //nH
            //对于每一行,逐列打印
            for (int i = 0; i < bmp.getWidth(); i++) {
                //每一列24个像素点,分为3个字节存储
                for (int m = 0; m < 3; m++) {
                    //每个字节表示8个像素点,0表示白色,1表示黑色
                    for (int n = 0; n < 8; n++) {
                        byte b = px2Byte(i, j * 24 + m * 8 + n, bmp);
                        data[k] += data[k] + b;
                    }
                    k++;
                }
            }
            data[k++] = 10;//换行
        }
        socketOut.write(data);
        socketOut.flush();
    }
}

 

WiFi打印小票到此基本上就可以了
下面开始我们的蓝牙打印
蓝牙打印的话首先就要有权限

//蓝牙权限 
<uses-permission android:name="android.permission.BLUETOOTH" />
 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
 再来看看蓝牙相关的布局 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <include layout="@layout/top_bar"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@color/colorGrayTertiary"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:text="选择一个已配对的打印设备 (请确保打印机和平板的蓝牙已开通)"
        android:textColor="@color/textColorSecondary"
        android:textSize="14sp" />

    <ListView
        android:id="@+id/lv_paired_devices"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@color/colorWhite"
        android:choiceMode="singleChoice"
        android:divider="@android:drawable/divider_horizontal_bright" />

    <LinearLayout
        android:layout_marginBottom="15dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal">
        <Button
            android:background="@drawable/submit_select"
            android:textColor="@color/white"
            android:id="@+id/btn_goto_setting"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:layout_marginLeft="@dimen/common_margin"
            android:layout_marginRight="@dimen/common_margin"
            android:text="还未配对打印机,去设置" />

        <Button
            android:background="@drawable/submit_select"
            android:textColor="@color/white"
            android:id="@+id/btn_test_conntect"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:layout_marginLeft="@dimen/common_margin"
            android:layout_marginRight="@dimen/common_margin"

            android:text="测试打印机连接" />

        <Button
            android:background="@drawable/submit_select"
            android:id="@+id/btn_print"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:layout_marginLeft="@dimen/common_margin"
            android:layout_marginRight="@dimen/common_margin"
            android:text="打印"
            android:textColor="@color/white" />
    </LinearLayout>
</LinearLayout>

 

接着具体看看代码里面怎么实现的,包括蓝牙的一些检索和设置 
public class PrinterSettingActivity extends BasePrintActivity implements View.OnClickListener{
    private Root root;
    private String result;
    private ObjBean obj;
    private ObjBean objBean;
    private List<ParentBean> foodsBean;
    private List<ListBean> listBeen;
    ListView mLvPairedDevices;
    Button mBtnSetting;
    Button mBtnTest;
    Button mBtnPrint;

    DeviceListAdapter mAdapter;
    int mSelectedPosition = -1;

    final static int TASK_TYPE_CONNECT = 1;
    final static int TASK_TYPE_PRINT = 2;

    private String id;
    private Pos pos;
    private OutputStream mOutputStream = null;
    private Bitmap head_bitmap;
    private Bitmap code_bitmap;
    private LinearLayout back;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_printer_setting);
        id = getIntent().getStringExtra("id");
        setTitle("蓝牙打印");
        initViews();
        print();//获取小票数据
    }


        private void print() {
            HttpUtil.ticket(this, id, new HttpUtil.KWiListener() {
                @Override
                public void onResult(int ret, Object msg) {
                    Log.d("tag", "打印小票: " + msg.toString());
                    Gson gson = new Gson();
                    String jsonString = msg.toString();
                    root = gson.fromJson(jsonString, Root.class);
                    result = root.getResult().getResultCode();
                    if (result.equals("0")) {
                        objBean = root.getObj();
                        foodsBean = objBean.getParent();

                    } else {
                        ToastUtil.show(root.getResult().getResultMessage());
                    }
                }
            });
        }


    @Override
    protected void onResume() {
        super.onResume();
        fillAdapter();
    }

    private void initViews() {
        back = (LinearLayout) findViewById(R.id.back);
        back.setOnClickListener(this);
        mLvPairedDevices = (ListView) findViewById(R.id.lv_paired_devices);
        mBtnSetting = (Button) findViewById(R.id.btn_goto_setting);
        mBtnTest = (Button) findViewById(R.id.btn_test_conntect);
        mBtnPrint = (Button) findViewById(R.id.btn_print);

        mLvPairedDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mSelectedPosition = position;
                mAdapter.notifyDataSetChanged();
            }
        });

        mBtnSetting.setOnClickListener(this);
        mBtnTest.setOnClickListener(this);
        mBtnPrint.setOnClickListener(this);

        mAdapter = new DeviceListAdapter(this);
        mLvPairedDevices.setAdapter(mAdapter);
    }

    /**
     * 从所有已配对设备中找出打印设备并显示
     */
    private void fillAdapter() {
        //推荐使用 BluetoothUtil.getPairedPrinterDevices()
        List<BluetoothDevice> printerDevices = BluetoothUtil.getPairedDevices();
        mAdapter.clear();
        mAdapter.addAll(printerDevices);
        refreshButtonText(printerDevices);
    }

    private void refreshButtonText(List<BluetoothDevice> printerDevices) {
        if (printerDevices.size() > 0) {
            mBtnSetting.setText("配对更多设备");
        } else {
            mBtnSetting.setText("还未配对打印机,去设置");
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_goto_setting:
                startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
                break;

            case R.id.btn_test_conntect:
                connectDevice(TASK_TYPE_CONNECT);
                break;

            case R.id.btn_print:
                connectDevice(TASK_TYPE_PRINT);
                break;
            case R.id.back:
                finish();
                break;
            default:
                break;
        }
    }

    private void connectDevice(int taskType){
        if(mSelectedPosition >= 0){
            BluetoothDevice device = mAdapter.getItem(mSelectedPosition);
            if(device!= null)
                super.connectDevice(device, taskType);
        }else{
            Toast.makeText(this, "还未选择打印设备", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onConnected(BluetoothSocket socket, int taskType) {
        switch (taskType){
            case TASK_TYPE_PRINT:
                if(socket != null&&socket.isConnected()){
                    pos(socket);
                }

                break;
        }
    }

    private void pos(final BluetoothSocket socket) {
        // 开启一个子线程
        new Thread() {
            public void run() {
                try {
                    //初始化打印机
                    pos = new Pos(socket.getOutputStream(),"GBK");
                    if (!TextUtils.isEmpty(objBean.getHead_img())){
                        pos.printLocation(1);
                        head_bitmap = pos.compressPic(returnBitMap(objBean.getHead_img()));
                        pos.draw2PxPoint(head_bitmap);
                    }
                    pos.printLocation(1);
                    pos.bold(true);
                    pos.printTabSpace(2);
                    pos.printWordSpace(1);
                    pos.printTextNewLine(objBean.getShop_name());

                    pos.printLocation(0);
                    pos.printTextNewLine("----------------------------------------------");
                    pos.bold(false);
                    pos.printTextNewLine("订 单 号:"+objBean.getSn());
                    pos.printTextNewLine("用 户 名:"+objBean.getMember());
                    pos.printTextNewLine("订单日期:"+objBean.getCreate_time());
                    pos.printTextNewLine("支付方式:"+objBean.getPay_way());
                    pos.printTextNewLine("订单折扣:"+objBean.getDiscount());
                    pos.printTextNewLine("订单备注:"+objBean.getRemarks());
                    pos.printLine(2);

                    pos.printText("货号          尺码    颜色    数量   小计");
                    pos.printLocation(20, 1);
                    pos.printTextNewLine("----------------------------------------------");

                    for (ParentBean foods : foodsBean) {
                        pos.printTextNewLine(foods.getGoods_name()+"          "+foods.getCode_number()+"     "+foods.getColour()+"      "+foods.getNum()+"      "+foods.getPay_back());
                        pos.printLocation(20, 1);

                    }

                    pos.printTextNewLine("----------------------------------------------");
                    pos.printLocation(0);
                    pos.printLine(1);
                    pos.printTextNewLine("订单总数:"+objBean.getNums());
                    pos.printTextNewLine("应收金额:"+objBean.getActual_pay());
                    pos.printTextNewLine("优惠金额:"+objBean.getDiscount_pay());
                    pos.printTextNewLine("实收金额:"+objBean.getPay());
                    pos.printLine(2);
                    //打印二维码  -- 如果提供了二维码的地址则用该方法
//                  pos.qrCode(objBean.getQr_code());


                    //打印二维码的图片 -- 如果提供了二维码的截图则用该方法
                    if (!TextUtils.isEmpty(objBean.getQr_code())){
                        pos.printLocation(1);
                        code_bitmap = pos.compressPic(returnBitMap(objBean.getQr_code()));
                        pos.draw2PxPoint(code_bitmap);
                    }
                    pos.printLine(4);
                    //切纸
                    pos.feedAndCut();
//                  pos.closeIOAndSocket();
                    pos = null;
                } catch (UnknownHostException e) {
                    Log.d("tag", "错误信息1:" + e.toString());
                } catch (IOException e) {
                    Log.d("tag", "错误信息2:" + e.toString());
                }
            }

        }.start();

    }
    class DeviceListAdapter extends ArrayAdapter<BluetoothDevice> {

        public DeviceListAdapter(Context context) {
            super(context, 0);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            BluetoothDevice device = getItem(position);
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_bluetooth_device, parent, false);
            }

            TextView tvDeviceName = (TextView) convertView.findViewById(R.id.tv_device_name);
            CheckBox cbDevice = (CheckBox) convertView.findViewById(R.id.cb_device);

            tvDeviceName.setText(device.getName());

            cbDevice.setChecked(position == mSelectedPosition);

            return convertView;
        }
    }
    public Bitmap returnBitMap(String url) {
        URL myFileUrl = null;
        Bitmap bitmap = null;
        try {
            myFileUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }
}


R.layout.item_bluetooth_device的布局如下: 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:paddingLeft="@dimen/common_margin"
    android:paddingRight="@dimen/common_margin">

    <TextView
        android:id="@+id/tv_device_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:text="蓝牙打印机"
        android:textColor="@color/textColorPrimary"
        android:textSize="14sp" />

    <android.support.v7.widget.AppCompatCheckBox
        android:id="@+id/cb_device"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:textSize="14sp" />

</RelativeLayout>


最后还是打印小票的方法 pos(socket);这个方法和之前WiFi方法基本一致,只是初始化不一样

private void pos(final BluetoothSocket socket) {
        // 开启一个子线程
        new Thread() {
            public void run() {
                try {
                    //初始化打印机
                    pos = new Pos(socket.getOutputStream(),"GBK");
                    if (!TextUtils.isEmpty(objBean.getHead_img())){
                        pos.printLocation(1);
                        head_bitmap = pos.compressPic(returnBitMap(objBean.getHead_img()));
                        pos.draw2PxPoint(head_bitmap);
                    }
                    pos.printLocation(1);
                    pos.bold(true);
                    pos.printTabSpace(2);
                    pos.printWordSpace(1);
                    pos.printTextNewLine(objBean.getShop_name());
 
                    pos.printLocation(0);
                    pos.printTextNewLine("----------------------------------------------");
                    pos.bold(false);
                    pos.printTextNewLine("订 单 号:"+objBean.getSn());
                    pos.printTextNewLine("用 户 名:"+objBean.getMember());
                    pos.printTextNewLine("订单日期:"+objBean.getCreate_time());
                    pos.printTextNewLine("支付方式:"+objBean.getPay_way());
                    pos.printTextNewLine("订单备注:"+objBean.getRemarks());
                    pos.printLine(2);
 
                    pos.printText("货号          尺码    颜色    数量   小计");
                    pos.printLocation(20, 1);
                    pos.printTextNewLine("----------------------------------------------");
 
                    for (ParentBean foods : foodsBean) {
                        pos.printTextNewLine(foods.getGoods_name()+"            "+foods.getCode_number()+"     "+foods.getColour()+"      "+foods.getNum()+"      "+foods.getPay_back());
                        pos.printLocation(20, 1);
 
                    }
 
                    pos.printTextNewLine("----------------------------------------------");
                    pos.printLocation(0);
                    pos.printLine(1);
                    pos.printTextNewLine("总数:"+objBean.getNums());
                    pos.printTextNewLine("合计:"+objBean.getPay());
                    pos.printLine(2);
                    //打印二维码  -- 如果提供了二维码的地址则用该方法
//                  pos.qrCode(objBean.getQr_code());
 
 
                    //打印二维码的图片 -- 如果提供了二维码的截图则用该方法
                    if (!TextUtils.isEmpty(objBean.getQr_code())){
                        pos.printLocation(1);
                        code_bitmap = pos.compressPic(returnBitMap(objBean.getQr_code()));//returnBitmap方法和上面WiFi的一样
                        pos.draw2PxPoint(code_bitmap);
                    }
                    pos.printLine(4);
                    //切纸
                    pos.feedAndCut();
//                  pos.closeIOAndSocket();
                    pos = null;
                } catch (UnknownHostException e) {
                    Log.d("tag", "错误信息1:" + e.toString());
                } catch (IOException e) {
                    Log.d("tag", "错误信息2:" + e.toString());
                }
            }
 
        }.start();
 
    }
 
到此的话基本两种方式都可以了,我用两台打印机试过都没问题

下载地址:https://download.csdn.net/download/u011056653/10567104