关于Android蓝牙打印和网络打印,其实都是利用Socket通信机制,只是蓝牙打印将socket做了一层封装BluetoothSocket ,打印的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。
在java.io包中操作文件内容的主要有两大类:字节流、字符流,两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类)
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。字节流主要是操作byte类型数据,以byte数组为准,而打印指令是以字节数组形式存在的,所以对于打印,我们使用字符流进行读写操作。
对于蓝牙打印,需要的操作有:
由于上述流程存在耗时操作,需要开一个线程,使用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个没什么问题,如果多了,机器可能撑不住而直接崩溃 ,这和机器的硬件有关。)