Android打印机--蓝牙打印

关于Android蓝牙打印和网络打印,其实都是利用Socket通信机制,只是蓝牙打印将socket做了一层封装BluetoothSocket ,打印的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。

在java.io包中操作文件内容的主要有两大类:字节流、字符流,两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类)

字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。字节流主要是操作byte类型数据,以byte数组为准,而打印指令是以字节数组形式存在的,所以对于打印,我们使用字符流进行读写操作。

 

对于蓝牙打印,需要的操作有:

 

  • 搜索蓝牙设备
  • 和蓝牙设备建立连接
  • 如果连接成功 则打印相应内容和命令(可以控制字体大小 等等一些指令)
  • 还可记住该台设备的蓝牙mac,下次可直接连接该设备进行打印

由于上述流程存在耗时操作,需要开一个线程,使用Thread+Handler处理

 

/**
 * 保持蓝牙连接的线程
 */
public class BluetoothThread extends Thread {

    // 固定不变,表示蓝牙通用串口服务
    private static final UUID BLUETOOTH_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private BluetoothSocket mSocket; // 蓝牙连接的socket

    private OutputStream mOutputStream;   // 用于打印数据的输出流

    private Handler mHandler;
    private Callback mCallback;

    private BluetoothDevice mDevice;

    public BluetoothThread(BluetoothDevice bondedDevice) throws Exception {
        mDevice = bondedDevice;
        if (bondedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
            throw new Exception("BluetoothDevice has not bonded.");
        }

        try {
            mSocket = bondedDevice.createRfcommSocketToServiceRecord(BLUETOOTH_UUID);  // 创建连接的Socket对象
            mSocket.connect();

            mOutputStream = mSocket.getOutputStream();
        } catch (IOException e) {
            if (mSocket != null) {
                try {
                    mSocket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

            throw new Exception("BluetoothDevice connect fail. " + e.getMessage());
        }
    }

    public void quit() {
        if (mHandler == null) {
            return;
        }

        mHandler.sendEmptyMessage(-1);
    }

    public void write(String text) {
        byte[] bytes = new byte[0];
        try {
            bytes = text.getBytes("GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        write(bytes);
    }

    public void write(byte[] bytes) {
        if (mHandler == null) {
            return;
        }
        Message msg = mHandler.obtainMessage(0);
        msg.obj = bytes;
        mHandler.sendMessage(msg);
    }

    public boolean isInnerPrinter() {
        return "00:11:22:33:44:55".equals(mDevice.getAddress());
    }

    @Override
    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == -1) {
                    Looper looper = Looper.myLooper();
                    if (looper != null) {
                        looper.quit();
                    }
                    removeCallbacksAndMessages(null);
                    mHandler = null;
                } else {
                    byte[] bytes = (byte[]) msg.obj;
                    try {

                        mOutputStream.write(bytes);

                        if (mCallback != null) {
                            mCallback.onWriteFinished(mDevice);
                        }
                    } catch (IOException e) {
                        if (mCallback != null) {
                            mCallback.onWriteFail(mDevice);
                        }
                    }
                }
            }
        };

        Looper.loop();

        // 线程结束,则关闭
        try {
            mOutputStream.close();
            mSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setCallback(Callback callback) {
        mCallback = callback;
    }

    interface Callback {
        void onWriteFinished(BluetoothDevice device);

        void onWriteFail(BluetoothDevice device);
    }
}


对于蓝牙连接和打印定义一个蓝牙管理类

 

/**
 * 负责蓝牙相关的业务逻辑
 */
public class BluetoothManager {

    private static BluetoothManager sBluetoothManager; // 防止创建多次,设置为单例

    private Map mBluetoothThreadMap = new HashMap<>();   // 存储每个蓝牙设备连接成功时对应连接的线程
    private int mPrintingThreadCount = 0;

    private BluetoothManager() {
        // 通过getInstance()方法获取实例
    }

    /**
     * 获取当前类示例
     */
    public synchronized static BluetoothManager getInstance() {
        if (sBluetoothManager == null) {
            sBluetoothManager = new BluetoothManager();
        }
        return sBluetoothManager;
    }

    /**
     * 连接蓝牙设备
     */
    public boolean connect(BluetoothDevice device, Context context) {
        BluetoothAdapter.getDefaultAdapter().cancelDiscovery();

        BluetoothThread thread = mBluetoothThreadMap.get(device);
        if (thread == null) {
            try {
                thread = new BluetoothThread(device);
                thread.start();

                mBluetoothThreadMap.put(device, thread);

                // 连接的蓝牙设备无法确定的判断出是否是打印机,所以将所有连接上的蓝牙设备全部放到PrinterManager中
                PrinterManager.getInstance().register(GeneralPrinter.getPrinterThroughBluetooth(context, device.getAddress(), device.getName(), thread));

                return true;
            } catch (Exception e) {
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 断开当前正在连接的蓝牙设备
     */
    public void disconnect(Context context, BluetoothDevice device) {
        BluetoothThread thread = mBluetoothThreadMap.get(device);
        if (thread != null) {
            thread.quit();
            mBluetoothThreadMap.remove(device);

            // 断开连接时从PrinterManager中去除
            PrinterManager.getInstance().unregister(context, device.getAddress());
        }
    }

    /**
     * 断开所有设备
     */
    public void disconnectAll() {
        for (BluetoothThread thread : mBluetoothThreadMap.values()) {
            thread.quit();
        }

        mBluetoothThreadMap.clear();
    }

    /**
     * 获取已经连接成功的蓝牙设备
     */
    public List getConnectedDeviceList() {
        return new ArrayList<>(mBluetoothThreadMap.keySet());
    }

    public boolean hasConnectedDevice() {
        return !mBluetoothThreadMap.isEmpty();
    }

    private void preparePrint() {
        int count;
        do {
            synchronized (BluetoothManager.class) {
                count = mPrintingThreadCount;
                if (count <= 0) {
                    mPrintingThreadCount = mBluetoothThreadMap.size();
                }
            }
        } while (count > 0);
    }

    public void printText(String text, final OnPrintListener listener) {
        if (TextUtils.isEmpty(text)) {
            return;
        }

        preparePrint();

        for (final BluetoothThread thread : mBluetoothThreadMap.values()) {
            if (thread.isInnerPrinter()) {
                IPrinter innerPrinter = PrinterManager.getInstance().getInnerPrinter();
                if (innerPrinter != null) {
                    synchronized (BluetoothManager.class) {
                        mPrintingThreadCount--;
                        if (mPrintingThreadCount <= 0) {
                            if (listener != null) {
                                listener.onPrintFinished();
                            }
                        }
                    }
                    continue;
                }
            }

            thread.setCallback(new BluetoothThread.Callback() {
                @Override
                public void onWriteFinished(BluetoothDevice device) {
                    thread.setCallback(null);

                    synchronized (BluetoothManager.class) {
                        mPrintingThreadCount--;
                        if (mPrintingThreadCount <= 0) {
                            if (listener != null) {
                                listener.onPrintFinished();
                            }
                        }
                    }
                }

                @Override
                public void onWriteFail(BluetoothDevice device) {
                    thread.setCallback(null);
                    if (listener != null) {
                        listener.onPrintFail(device);
                    }
                    synchronized (BluetoothManager.class) {
                        mPrintingThreadCount--;
                        if (mPrintingThreadCount <= 0) {
                            if (listener != null) {
                                listener.onPrintFinished();
                            }
                        }
                    }
                }
            });

            thread.write(text);
        }
    }

    public void printText(byte[] bytes, final OnPrintListener listener) {
        if (TextUtils.isEmpty(Arrays.toString(bytes))) {
            return;
        }

        preparePrint();

        for (final BluetoothThread thread : mBluetoothThreadMap.values()) {
            if (thread.isInnerPrinter()) {
                IPrinter innerPrinter = PrinterManager.getInstance().getInnerPrinter();
                if (innerPrinter != null) {
                    synchronized (BluetoothManager.class) {
                        mPrintingThreadCount--;
                        if (mPrintingThreadCount <= 0) {
                            if (listener != null) {
                                listener.onPrintFinished();
                            }
                        }
                    }
                    continue;
                }
            }

            thread.setCallback(new BluetoothThread.Callback() {
                @Override
                public void onWriteFinished(BluetoothDevice device) {
                    thread.setCallback(null);

                    synchronized (BluetoothManager.class) {
                        mPrintingThreadCount--;
                        if (mPrintingThreadCount <= 0) {
                            if (listener != null) {
                                listener.onPrintFinished();
                            }
                        }
                    }
                }

                @Override
                public void onWriteFail(BluetoothDevice device) {
                    thread.setCallback(null);
                    if (listener != null) {
                        listener.onPrintFail(device);
                    }
                    synchronized (BluetoothManager.class) {
                        mPrintingThreadCount--;
                        if (mPrintingThreadCount <= 0) {
                            if (listener != null) {
                                listener.onPrintFinished();
                            }
                        }
                    }
                }
            });

            thread.write(bytes);
        }
    }

    /**
     * 指定某个蓝牙设备打印文本内容
     *
     * @param text 打印的文本内容
     */
    public void printText(BluetoothDevice device, String text, final OnPrintListener listener) {
        if (TextUtils.isEmpty(text)) {
            return;
        }

        final BluetoothThread thread = mBluetoothThreadMap.get(device);
        if (thread != null) {
            if (listener != null) {
                thread.setCallback(new BluetoothThread.Callback() {
                    @Override
                    public void onWriteFinished(BluetoothDevice device) {
                        thread.setCallback(null);
                        listener.onPrintFinished();
                    }

                    @Override
                    public void onWriteFail(BluetoothDevice device) {
                        thread.setCallback(null);
                        listener.onPrintFail(device);
                    }
                });
            }

            thread.write(text);  // 打印文本
        }
    }

    public interface OnPrintListener {
        void onPrintFinished();

        void onPrintFail(BluetoothDevice device);
    }
}


以上就是Android蓝牙打印整个流程,蓝牙打印可以同时连接多个打印机(一般情况下连2-3个没什么问题,如果多了,机器可能撑不住而直接崩溃 ,这和机器的硬件有关。)

 

 

 

 

 

你可能感兴趣的:(Android,打印机)