一、打印的效果图,打印照片+二维码+文字

android 链接蓝牙打印机 安卓调用蓝牙打印机_Android蓝牙打印图片

二、蓝牙相关组件介绍

/**
     * 代表本地蓝牙适配器(蓝牙无线电)。BluetoothAdapter是所有蓝牙交互的入口。
     * 使用这个你可以发现其他蓝牙设备,查询已配对的设备列表,
     * 使用一个已知的MAC地址来实例化一个BluetoothDevice,
     * 以及创建一个BluetoothServerSocket来为监听与其他设备的通信。
     */
    private BluetoothAdapter mBluetoothAdapter = null;


    /**
     * 代表一个远程蓝牙设备,使用这个来请求一个与远程设备的BluetoothSocket连接,
     * 或者查询关于设备名称、地址、类和连接状态等设备信息。
     */
    private BluetoothDevice mBluetoothDevice = null;

    /**
     * 代表一个蓝牙socket的接口(和TCP Socket类似)。这是一个连接点,
     * 它允许一个应用与其他蓝牙设备通过InputStream和OutputStream交换数据。
     */
    private BluetoothSocket mBluetoothSocket = null;

三、搜索蓝牙设备

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_search_device);

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        //注册设备被发现时的广播
        IntentFilter filter1=new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver,filter1);
        //注册一个搜索结束时的广播
        IntentFilter filter2=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(mReceiver,filter2);

        IntentFilter filter3=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        registerReceiver(mReceiver,filter3);

        IntentFilter filter4=new IntentFilter(BluetoothAdapter.ACTION_REQUEST_ENABLE);  // 开关变化的广播
        registerReceiver(mReceiver,filter4);



        Button btn = (Button)findViewById(R.id.btnV1);   //  设备搜索
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mBluetoothAdapter != null){
                    if(!mBluetoothAdapter.isEnabled()){  // 蓝牙开关是否打开
                        mBluetoothAdapter.enable();
                    }else{
                        Log.d(TAG,"mBluetoothAdapter.isEnabled() == true");
                    }
                    mBluetoothAdapter.startDiscovery();  // 开始搜索蓝牙设备,通过监听广播接收搜索到的设备
                }else{
                    Toast.makeText(SearchBlueToothActivity.this,"该设备没有蓝牙模块",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    /**
     * 接收搜索蓝牙设备结果的信息
     */
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)){
                BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.d(TAG,"device = " + device);
                if(device.getBondState()==BluetoothDevice.BOND_BONDED){    //显示已配对设备
                    Log.d(TAG,"已配对设备 : " + device.getName() + ", " + device.getName());
                }else{
                    Log.d(TAG,"未配对设备 : " + device.getName() + ", " + device.getName());
                }

            }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
                Log.d(TAG,"搜索完成...");
            }else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
                Log.d(TAG,"搜索开始...");
            }else if(BluetoothAdapter.ACTION_REQUEST_ENABLE.equals(action)){
                Log.d(TAG,"蓝牙打开...");
            }
        }
    };

四、蓝牙打印 // 这里写死了,要修改获取蓝牙设备的方式

public class BtPrint {
    private static BtPrint instance;
    public static String TAG = BtPrint.class.getSimpleName();
    private List<String> mpairedDeviceList = new ArrayList<String>();

    private BluetoothAdapter mBluetoothAdapter = null;

    private BluetoothDevice mBluetoothDevice = null;

    private BluetoothSocket mBluetoothSocket = null;

    private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private OutputStream mOutputStream = null;
    Set<BluetoothDevice> pairedDevices = null;

    /**
     * @return
     * @throws
     * @Title: getInstance
     */
    public static BtPrint getInstance() {
        if (instance == null) {
            synchronized (BtPrint.class) {
                if (instance == null) {
                    instance = new BtPrint();
                }
            }
        }
        return instance;
    }

    public void releasePrint(){
        mBluetoothAdapter = null;
        if(mBluetoothSocket != null){
            try {
                mBluetoothSocket.close();
                mBluetoothSocket = null;
            } catch (IOException e) {
                e.printStackTrace();
                Log.d(TAG,"releasePrint(),IOException :",e);
                mBluetoothSocket = null;
            }
        }
    }

    /**
     * 连接打印机设备
     */
    public void connectPrinter(){
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if(mBluetoothAdapter == null){   // 蓝牙功能没有打开,UI界面弹出打开蓝牙功能
            Log.d(TAG,"connectPrinter(),mBluetoothAdapter = null");
        }else if(mBluetoothAdapter.isEnabled()){  // 蓝牙已经打开
            // 列出已经配对过的设备
            String getName = mBluetoothAdapter.getName();
            Log.d(TAG, "getName = " + getName);
            pairedDevices = mBluetoothAdapter.getBondedDevices(); // 已经配对了的设备?
            while (mpairedDeviceList.size() > 1) {
                mpairedDeviceList.remove(1);
            }
            if (pairedDevices.size() == 0) {
                Log.d(TAG,"connectPrinter(),pairedDevices.size == 0");
                return;  // 没有配对过的设备
            }
            for (BluetoothDevice device : pairedDevices) {
                getName = device.getAddress();
                mpairedDeviceList.add(getName);//蓝牙名
            }
            String temString = mpairedDeviceList.get(0);
            Log.d(TAG,"temString = " + temString + ", mBluetoothDevice = " + mBluetoothDevice);

            mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(temString);
            try {
                mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(SPP_UUID);
                mBluetoothSocket.connect();
                Log.d(TAG,"mBluetoothDevice = " + mBluetoothDevice +", mBluetoothSocket = " + mBluetoothSocket);
            } catch (IOException e) {
                Log.d(TAG,"connectPrinter(),IOException :",e);
            }
        }else {  // 蓝牙未打开
            Log.d(TAG,"connectPrinter(),bluetooth isnot open");
        }
    }

    private  static int printTimes = 0;  // 出错时重试打印的次数

    /**
     * 打印小条
     */
    public void printVerifyData(String tmpName,
                                String tmpIdNo,
                                String curName,
                                String idcardNo,
                                String headerPic) {
        if(mBluetoothSocket == null){
            connectPrinter();
        }else{
            if(!mBluetoothSocket.isConnected()){
                try {
                    mBluetoothSocket.connect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
                Log.d(TAG,"printVerifyData(),mBluetoothSocket.isConnected.");
            }
        }

        // 打印图片
        // 打印标题
        String title = Const.VALUE.TITLE;
        String line = ".......................................";
        try {
            mOutputStream = mBluetoothSocket.getOutputStream();
            PrintUtils PrintUtils = new PrintUtils();
            PrintUtils.setOutputStream(mOutputStream);
            PrintUtils.selectCommand(PrintUtils.RESET);
            PrintUtils.selectCommand(PrintUtils.LINE_SPACING_DEFAULT);
            PrintUtils.selectCommand(PrintUtils.LINE_SPACING);
            PrintUtils.selectCommand(PrintUtils.ALIGN_CENTER);
            PrintUtils.selectCommand(PrintUtils.BOLD);
            PrintUtils.selectCommand(PrintUtils.DOUBLE_HEIGHT_WIDTH);  //宽高加倍
            PrintUtils.printText(title + "\n");
            PrintUtils.selectCommand(PrintUtils.BOLD_CANCEL);
            PrintUtils.selectCommand(PrintUtils.NORMAL);
            PrintUtils.printText(line + "\n");

            // 打印照片
            Bitmap image = ImageUtils.getBitmap(headerPic);

            image = convertGreyImgByFloyd(image);
            byte[]imageData = PrinterUtils.decodeBitmap(image);
            PrintUtils.selectCommand(imageData);
            PrintUtils.printText(line + "\n");

            PrintUtils.selectCommand(PrintUtils.ALIGN_CENTER);
            PrintUtils.selectCommand(PrintUtils.BOLD);
            Log.d(TAG,"BtPrint # tmpName = " + tmpName + ",tmpIdNo = " + tmpIdNo);
            PrintUtils.printText(PrintUtils.printTwoData("姓名:", tmpName +"\n"));
            PrintUtils.printText(PrintUtils.printTwoData("身份证号码:", tmpIdNo+"\n"));
            PrintUtils.printText(PrintUtils.printTwoData("凭证有效期:", TimeUtils.date2String(new Date(),new SimpleDateFormat("yyyy年MM月dd日"))+"\n"));

            PrintUtils.selectCommand(PrintUtils.BOLD_CANCEL);
            PrintUtils.printText(line + "\n");
            String oriString = curName+"|" +idcardNo;
            Log.d(TAG,"BtPrint # oriString = " + oriString);
            String qrString = Base64.encodeToString(oriString.getBytes("UTF-8"),Base64.NO_WRAP);
            Log.d(TAG,"qrString = " + qrString);
            Bitmap qrCodeImage = QRCodeUtil.createQRCodeBitmap(qrString, 300, "0");
            byte[] qrData = PrinterUtils.decodeBitmap(qrCodeImage);
            PrintUtils.selectCommand(qrData);

            PrintUtils.printText(line + "\n");
            PrintUtils.selectCommand(PrintUtils.NORMAL);
            PrintUtils.selectCommand(PrintUtils.ALIGN_LEFT);
            PrintUtils.selectCommand(PrintUtils.BOLD);
            PrintUtils.selectCommand(PrintUtils.COLUMN_SPACING);
            String tips1 = " lajdflajdfl,"+ "\n";
            String tips2 = " lasdjflkajsdlfjalksdjflajsdflja"+"\n";
            PrintUtils.printText(tips1);
            PrintUtils.printText(tips2);
            PrintUtils.selectCommand(PrintUtils.BOLD_CANCEL);
            PrintUtils.selectCommand(PrintUtils.COLUMN_SPACING_CANCEL);
            PrintUtils.printText("\n\n");
            // 切纸
            mOutputStream = mBluetoothSocket.getOutputStream();
            mOutputStream.write(new byte[]{0x0a, 0x0a, 0x1d, 0x56, 0x01});
            mOutputStream.flush();

            BusEvent busEvent = new BusEvent();
            busEvent.action = "printer_completed";
            busEvent.data = "ok";
            EventBus.getDefault().post(busEvent);
        } catch (Exception e) {
            Log.d(TAG, "print error printTimes = " + printTimes);
            if(printTimes < 5){
                printTimes ++;
                printVerifyData(tmpName,tmpIdNo,curName,idcardNo,headerPic);
            }else{
                Log.d(TAG, "print error :", e);
                LogUtils.file(e.getCause() + "--" + e.getMessage());
                sendPrintErr();
            }
        }
    }

    /**
     * 发送打印错误的信息
     */
    private void sendPrintErr(){
        BusEvent busEvent = new BusEvent();
        busEvent.action = "printer_completed";
        busEvent.data = "error";
        EventBus.getDefault().post(busEvent);
        BtPrint.getInstance().releasePrint();
    }

    public Bitmap convertGreyImgByFloyd(Bitmap img) {
        int width = img.getWidth();
        //获取位图的宽
        int height = img.getHeight();
        //获取位图的高 \
        int[] pixels = new int[width * height];
        //通过位图的大小创建像素点数组
        img.getPixels(pixels, 0, width, 0, 0, width, height);
        int[] gray = new int[height * width];
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int grey = pixels[width * i + j];
                int red = ((grey & 0x00FF0000) >> 16);
                gray[width * i + j] = red;
            }
        }
        int e = 0;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int g = gray[width * i + j];
                if (g >= 128) {
                    pixels[width * i + j] = 0xffffffff;
                    e = g - 255;
                } else {
                    pixels[width * i + j] = 0xff000000;
                    e = g - 0;
                }
                if (j < width - 1 && i < height - 1) {
                    //右边像素处理
                    gray[width * i + j + 1] += 3 * e / 8;
                    //下
                    gray[width * (i + 1) + j] += 3 * e / 8;
                    //右下
                    gray[width * (i + 1) + j + 1] += e / 4;
                } else if (j == width - 1 && i < height - 1) {
                    //靠右或靠下边的像素的情况
                    //下方像素处理
                    gray[width * (i + 1) + j] += 3 * e / 8;
                } else if (j < width - 1 && i == height - 1) {
                    //右边像素处理
                    gray[width * (i) + j + 1] += e / 4;
                }
            }
        }
        Bitmap mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        mBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return mBitmap;
    }
}

PrintUtils

import android.annotation.SuppressLint;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;

public class PrintUtils {

    private static final int LINE_BYTE_SIZE = 32;
    private static OutputStream outputStream = null;

    public static void setOutputStream(OutputStream outputStream) {
        PrintUtils.outputStream = outputStream;
    }


    /**
     * 打印文字
     *
     * @param text 要打印的文字
     */
    public static void printText(String text) {
        try {
            byte[] data = text.getBytes("gbk");
            outputStream.write(data, 0, data.length);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置打印格式
     *
     * @param command 格式指令
     */
    public static void selectCommand(byte[] command) {
        try {
            outputStream.write(command);
            outputStream.flush();
        } catch (IOException e) {
            //Toast.makeText(this.context, "发送失败!", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    /**
     * 复位打印机
     */
    public static final byte[] RESET = {0x1b, 0x40};

    /**
     * 左对齐
     */
    public static final byte[] ALIGN_LEFT = {0x1b, 0x61, 0x00};

    /**
     * 中间对齐
     */
    public static final byte[] ALIGN_CENTER = {0x1b, 0x61, 0x01};

    /**
     * 选择加粗模式
     */
    public static final byte[] BOLD = {0x1b, 0x45, 0x01};

    /**
     * 取消加粗模式
     */
    public static final byte[] BOLD_CANCEL = {0x1b, 0x45, 0x00};

    /**
     * 宽高加倍
     */
    public static final byte[] DOUBLE_HEIGHT_WIDTH = {0x1d, 0x21, 0x11};

    /**
     * 字体不放大
     */
    public static final byte[] NORMAL = {0x1d, 0x21, 0x00};

    /**
     * 设置默认行间距
     */
    public static final byte[] LINE_SPACING_DEFAULT = {0x1b, 0x32};

//    /**
//     * 设置行间距
//     */
	public static final byte[] LINE_SPACING = {0x1b, 0x33, 0x50};  // 20的行间距(0,255)

    /**
     * 设置字符间距
     */
    public static final byte[] COLUMN_SPACING = {0x1b, 0x20, 0x25};

    /**
     * 取消设置字符间距
     */
    public static final byte[] COLUMN_SPACING_CANCEL = {0x1b, 0x20, 0x00};

    /**
     * 打印两列
     *
     * @param leftText  左侧文字
     * @param rightText 右侧文字
     * @return
     */
    @SuppressLint("NewApi")
    public static String printTwoData(String leftText, String rightText) {
        StringBuilder sb = new StringBuilder();
        int leftTextLength = getBytesLength(leftText);
        int rightTextLength = getBytesLength(rightText);
        sb.append(leftText);

        // 计算两侧文字中间的空格
        int marginBetweenMiddleAndRight = LINE_BYTE_SIZE - leftTextLength - rightTextLength;

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

    /**
     * 获取数据长度
     *
     * @param msg
     * @return
     */
    @SuppressLint("NewApi")
    private static int getBytesLength(String msg) {
        return msg.getBytes(Charset.forName("GB2312")).length;
    }
}