蓝牙自动连接已配对设备
private void connectBluetooth(){BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();if (pairedDevices.size()!=0){for (BluetoothDevice device : pairedDevices) {connect(device.getAddress());}}else {Toasts.show(\"暂无配对设备\");}}
根据蓝牙地址,初始化线程池去做连接操作
private void connect(String address){//初始化话DeviceConnFactoryManagerdeviceConnFactoryManager=new DeviceConnFactoryManager.Build().setId(0)//设置连接方式.setConnMethod(DeviceConnFactoryManager.CONN_METHOD.BLUETOOTH)//设置连接的蓝牙mac地址.setMacAddress(address).build();//打开端口ThreadPool.getInstantiation().addTask(new Runnable() {@Overridepublic void run() {DeviceConnFactoryManager.getDeviceConnFactoryManagers()[0].openPort();}});}
DeviceConnFactoryManager.java
public class DeviceConnFactoryManager {public PortManager mPort;private static final String TAG = DeviceConnFactoryManager.class.getSimpleName();public CONN_METHOD connMethod;private String ip;private int port;private String macAddress;private UsbDevice mUsbDevice;private Context mContext;private String serialPortPath;private int baudrate;private int id;private static DeviceConnFactoryManager[] deviceConnFactoryManagers = new DeviceConnFactoryManager[4];private boolean isOpenPort;/*** ESC查询打印机实时状态指令*/private byte[] esc = {0x10, 0x04, 0x02};/*** ESC查询打印机实时状态 缺纸状态*/private static final int ESC_STATE_PAPER_ERR = 0x20;/*** ESC指令查询打印机实时状态 打印机开盖状态*/private static final int ESC_STATE_COVER_OPEN = 0x04;/*** ESC指令查询打印机实时状态 打印机报错状态*/private static final int ESC_STATE_ERR_OCCURS = 0x40;/*** TSC查询打印机状态指令*/private byte[] tsc = {0x1b, \'!\', \'?\'};/*** TSC指令查询打印机实时状态 打印机缺纸状态*/private static final int TSC_STATE_PAPER_ERR = 0x04;/*** TSC指令查询打印机实时状态 打印机开盖状态*/private static final int TSC_STATE_COVER_OPEN = 0x01;/*** TSC指令查询打印机实时状态 打印机出错状态*/private static final int TSC_STATE_ERR_OCCURS = 0x80;private byte[] cpcl={0x1b,0x68};/*** CPCL指令查询打印机实时状态 打印机缺纸状态*/private static final int CPCL_STATE_PAPER_ERR = 0x01;/*** CPCL指令查询打印机实时状态 打印机开盖状态*/private static final int CPCL_STATE_COVER_OPEN = 0x02;private byte[] sendCommand;/*** 判断打印机所使用指令是否是ESC指令*/private PrinterCommand currentPrinterCommand;public static final byte FLAG = 0x10;private static final int READ_DATA = 10000;private static final String READ_DATA_CNT = \"read_data_cnt\";private static final String READ_BUFFER_ARRAY = \"read_buffer_array\";public static final String ACTION_CONN_STATE = \"action_connect_state\";public static final String ACTION_QUERY_PRINTER_STATE = \"action_query_printer_state\";public static final String STATE = \"state\";public static final String DEVICE_ID = \"id\";public static final int CONN_STATE_DISCONNECT = 0x90;public static final int CONN_STATE_CONNECTING = CONN_STATE_DISCONNECT << 1;public static final int CONN_STATE_FAILED = CONN_STATE_DISCONNECT << 2;public static final int CONN_STATE_CONNECTED = CONN_STATE_DISCONNECT << 3;public PrinterReader reader;private String status=\"打印机连接正常\";public enum CONN_METHOD {//蓝牙连接BLUETOOTH(\"BLUETOOTH\"),//USB连接USB(\"USB\"),//wifi连接WIFI(\"WIFI\"),//串口连接SERIAL_PORT(\"SERIAL_PORT\");private String name;private CONN_METHOD(String name) {this.name = name;}@Overridepublic String toString() {return this.name;}}public static DeviceConnFactoryManager[] getDeviceConnFactoryManagers() {return deviceConnFactoryManagers;}/*** 打开端口** @return*/public void openPort() {deviceConnFactoryManagers[id].isOpenPort = false;sendStateBroadcast(CONN_STATE_CONNECTING);switch (deviceConnFactoryManagers[id].connMethod) {case BLUETOOTH:System.out.println(\"id -> \" + id);mPort = new BluetoothPort(macAddress);isOpenPort = deviceConnFactoryManagers[id].mPort.openPort();break;case USB:mPort = new UsbPort(mContext, mUsbDevice);isOpenPort = mPort.openPort();if (isOpenPort) {IntentFilter filter = new IntentFilter(ACTION_USB_DEVICE_DETACHED);mContext.registerReceiver(usbStateReceiver, filter);}break;case WIFI:mPort = new EthernetPort(ip, port);isOpenPort = mPort.openPort();break;case SERIAL_PORT:mPort = new SerialPort(serialPortPath, baudrate, 0);isOpenPort = mPort.openPort();break;default:break;}//端口打开成功后,检查连接打印机所使用的打印机指令ESC、TSCif (isOpenPort) {queryCommand();} else {if (this.mPort != null) {this.mPort=null;}sendStateBroadcast(CONN_STATE_FAILED);}}/*** 查询当前连接打印机所使用打印机指令(ESC(EscCommand.java)、TSC(LabelCommand.java))*/private void queryCommand() {//开启读取打印机返回数据线程reader = new PrinterReader();reader.start(); //读取数据线程//查询打印机所使用指令queryPrinterCommand(); //}/*** 获取端口连接方式** @return*/public CONN_METHOD getConnMethod() {return connMethod;}/*** 获取端口打开状态(true 打开,false 未打开)** @return*/public boolean getConnState() {return isOpenPort;}/*** 获取连接蓝牙的物理地址** @return*/public String getMacAddress() {return macAddress;}/*** 获取连接网口端口号** @return*/public int getPort() {return port;}/*** 获取连接网口的IP** @return*/public String getIp() {return ip;}/*** 获取连接的USB设备信息** @return*/public UsbDevice usbDevice() {return mUsbDevice;}/*** 关闭端口*/public void closePort(int id) {if (this.mPort != null) {System.out.println(\"id -> \" + id);reader.cancel();boolean b= this.mPort.closePort();if(b) {this.mPort=null;isOpenPort = false;currentPrinterCommand = null;}}sendStateBroadcast(CONN_STATE_DISCONNECT);}/*** 获取串口号** @return*/public String getSerialPortPath() {return serialPortPath;}/*** 获取波特率** @return*/public int getBaudrate() {return baudrate;}public static void closeAllPort() {for (DeviceConnFactoryManager deviceConnFactoryManager : deviceConnFactoryManagers) {if (deviceConnFactoryManager != null) {Log.e(TAG, \"cloaseAllPort() id -> \" + deviceConnFactoryManager.id);deviceConnFactoryManager.closePort(deviceConnFactoryManager.id);deviceConnFactoryManagers[deviceConnFactoryManager.id] = null;}}}private DeviceConnFactoryManager(Build build) {this.connMethod = build.connMethod;this.macAddress = build.macAddress;this.port = build.port;this.ip = build.ip;this.mUsbDevice = build.usbDevice;this.mContext = build.context;this.serialPortPath = build.serialPortPath;this.baudrate = build.baudrate;this.id = build.id;deviceConnFactoryManagers[id] = this;}/*** 获取当前打印机指令** @return PrinterCommand*/public PrinterCommand getCurrentPrinterCommand() {return deviceConnFactoryManagers[id].currentPrinterCommand;}public static final class Build {private String ip;private String macAddress;private UsbDevice usbDevice;private int port;private CONN_METHOD connMethod;private Context context;private String serialPortPath;private int baudrate;private int id;public DeviceConnFactoryManager.Build setIp(String ip) {this.ip = ip;return this;}public DeviceConnFactoryManager.Build setMacAddress(String macAddress) {this.macAddress = macAddress;return this;}public DeviceConnFactoryManager.Build setUsbDevice(UsbDevice usbDevice) {this.usbDevice = usbDevice;return this;}public DeviceConnFactoryManager.Build setPort(int port) {this.port = port;return this;}public DeviceConnFactoryManager.Build setConnMethod(CONN_METHOD connMethod) {this.connMethod = connMethod;return this;}public DeviceConnFactoryManager.Build setContext(Context context) {this.context = context;return this;}public DeviceConnFactoryManager.Build setId(int id) {this.id = id;return this;}public DeviceConnFactoryManager.Build setSerialPort(String serialPortPath) {this.serialPortPath = serialPortPath;return this;}public DeviceConnFactoryManager.Build setBaudrate(int baudrate) {this.baudrate = baudrate;return this;}public DeviceConnFactoryManager build() {return new DeviceConnFactoryManager(this);}}public void sendDataImmediately(final Vector<Byte> data) {if (this.mPort == null) {return;}try {// Log.e(TAG, \"data -> \" + new String(com.gprinter.command.GpUtils.convertVectorByteTobytes(data), \"gb2312\"));this.mPort.writeDataImmediately(data, 0, data.size());} catch (Exception e) {e.printStackTrace();}}public int readDataImmediately(byte[] buffer) throws IOException {return this.mPort.readData(buffer);}/*** 查询打印机当前使用的指令(TSC、ESC)*/private void queryPrinterCommand() {//线程池添加任务ThreadPool.getInstantiation().addTask(new Runnable() {@Overridepublic void run() {//发送ESC查询打印机状态指令sendCommand = esc;Vector<Byte> data = new Vector<>(esc.length);for (int i = 0; i < esc.length; i++) {data.add(esc[i]);}sendDataImmediately(data); //发送esc数据//开启计时器,隔2000毫秒没有没返回值时发送TSC查询打印机状态指令final ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(\"Timer\");final ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1, threadFactoryBuilder);scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {@Overridepublic void run() {if (currentPrinterCommand == null || currentPrinterCommand != PrinterCommand.ESC) {Log.e(TAG, Thread.currentThread().getName());//发送TSC查询打印机状态指令sendCommand = tsc;Vector<Byte> data = new Vector<>(tsc.length);for (int i = 0; i < tsc.length; i++) {data.add(tsc[i]);}sendDataImmediately(data);//开启计时器,隔2000毫秒没有没返回值时发送CPCL查询打印机状态指令scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {@Overridepublic void run() {if (currentPrinterCommand == null||(currentPrinterCommand != PrinterCommand.ESC&¤tPrinterCommand != PrinterCommand.TSC)) {Log.e(TAG, Thread.currentThread().getName());//发送CPCL查询打印机状态指令sendCommand=cpcl;Vector<Byte> data =new Vector<Byte>(cpcl.length);for (int i=0;i<cpcl.length;i++){data.add(cpcl[i]);}sendDataImmediately(data);//开启计时器,隔2000毫秒打印机没有响应者停止读取打印机数据线程并且关闭端口scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {@Overridepublic void run() {if(currentPrinterCommand==null){if (reader != null) {reader.cancel();mPort.closePort();isOpenPort = false;mPort=null;sendStateBroadcast(CONN_STATE_FAILED);}}}}),2000, TimeUnit.MILLISECONDS);}}}), 2000, TimeUnit.MILLISECONDS);}}}), 2000, TimeUnit.MILLISECONDS);}});}public class PrinterReader extends Thread {private boolean isRun = false;private byte[] buffer = new byte[100];public PrinterReader() {isRun = true;}@Overridepublic void run() {try {while (isRun) {//读取打印机返回信息int len = readDataImmediately(buffer);if (len > 0) {Message message = Message.obtain();message.what = READ_DATA;Bundle bundle = new Bundle();bundle.putInt(READ_DATA_CNT, len); //数据长度bundle.putByteArray(READ_BUFFER_ARRAY, buffer); //数据message.setData(bundle);mHandler.sendMessage(message);}}} catch (Exception e) {if (deviceConnFactoryManagers[id] != null) {closePort(id);}}}public void cancel() {isRun = false;}}private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case READ_DATA:int cnt = msg.getData().getInt(READ_DATA_CNT); //数据长度 >0;byte[] buffer = msg.getData().getByteArray(READ_BUFFER_ARRAY); //数据//这里只对查询状态返回值做处理,其它返回值可参考编程手册来解析if (buffer == null) {return;}int result = judgeResponseType(buffer[0]); //数据右移//String status = AppApplication.getInstance().getString(R.string.str_printer_conn_normal);if (sendCommand == esc) {//设置当前打印机模式为ESC模式if (currentPrinterCommand == null) {currentPrinterCommand = PrinterCommand.ESC;sendStateBroadcast(CONN_STATE_CONNECTED);} else {//查询打印机状态if (result == 0) {//打印机状态查询Intent intent = new Intent(ACTION_QUERY_PRINTER_STATE);intent.putExtra(DEVICE_ID, id);AppApplication.getInstance().sendBroadcast(intent);} else if (result == 1) {//查询打印机实时状态if ((buffer[0] & ESC_STATE_PAPER_ERR) > 0) {//缺纸status =AppApplication.getInstance().getString(R.string.str_printer_out_of_paper);ToastUtil.showToastWithImg(status,R.drawable.ico_fail);}if ((buffer[0] & ESC_STATE_COVER_OPEN) > 0) {//开盖status =AppApplication.getInstance().getString(R.string.str_printer_open_cover);ToastUtil.showToastWithImg(status,R.drawable.ico_fail);}if ((buffer[0] & ESC_STATE_ERR_OCCURS) > 0) {status =AppApplication.getInstance().getString(R.string.str_printer_error);ToastUtil.showToastWithImg(status,R.drawable.ico_fail);}System.out.println(AppApplication.getInstance().getString(R.string.str_state) + status);// String mode=AppApplication.getInstance().getString(R.string.str_printer_printmode_esc);//Utils.toast(AppApplication.getInstance(), mode+\" \"+status);}}} else if (sendCommand == tsc) {//设置当前打印机模式为TSC模式if (currentPrinterCommand == null) {currentPrinterCommand = PrinterCommand.TSC;sendStateBroadcast(CONN_STATE_CONNECTED);} else {if (cnt == 1) {//查询打印机实时状态if ((buffer[0] & TSC_STATE_PAPER_ERR) > 0) {//缺纸status =AppApplication.getInstance().getString(R.string.str_printer_out_of_paper);}if ((buffer[0] & TSC_STATE_COVER_OPEN) > 0) {//开盖status =AppApplication.getInstance().getString(R.string.str_printer_open_cover);}if ((buffer[0] & TSC_STATE_ERR_OCCURS) > 0) {//打印机报错status =AppApplication.getInstance().getString(R.string.str_printer_error);}System.out.println(AppApplication.getInstance().getString(R.string.str_state) + status);String mode=AppApplication.getInstance().getString(R.string.str_printer_printmode_tsc);Utils.toast(AppApplication.getInstance(), mode+\" \"+status);} else {//打印机状态查询Intent intent = new Intent(ACTION_QUERY_PRINTER_STATE);intent.putExtra(DEVICE_ID, id);AppApplication.getInstance().sendBroadcast(intent);}}}else if(sendCommand==cpcl){if (currentPrinterCommand == null) {currentPrinterCommand = PrinterCommand.CPCL;sendStateBroadcast(CONN_STATE_CONNECTED);}else {if (cnt == 1) {System.out.println(AppApplication.getInstance().getString(R.string.str_state) + status);if ((buffer[0] ==CPCL_STATE_PAPER_ERR)) {//缺纸status =AppApplication.getInstance().getString(R.string.str_printer_out_of_paper);}if ((buffer[0] ==CPCL_STATE_COVER_OPEN)) {//开盖status =AppApplication.getInstance().getString(R.string.str_printer_open_cover);}String mode=AppApplication.getInstance().getString(R.string.str_printer_printmode_cpcl);Utils.toast(AppApplication.getInstance(), mode+\" \"+status);} else {//打印机状态查询Intent intent = new Intent(ACTION_QUERY_PRINTER_STATE);intent.putExtra(DEVICE_ID, id);AppApplication.getInstance().sendBroadcast(intent);}}}break;default:break;}}};public String getStatus(){return status;}private void sendStateBroadcast(int state) {Intent intent = new Intent(ACTION_CONN_STATE);intent.putExtra(STATE, state);intent.putExtra(DEVICE_ID, id);AppApplication.getInstance().sendBroadcast(intent);}/*** 判断是实时状态(10 04 02)还是查询状态(1D 72 01)*/private int judgeResponseType(byte r) {return (byte) ((r & FLAG) >> 4);}BroadcastReceiver usbStateReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case ACTION_USB_DEVICE_DETACHED:sendStateBroadcast(CONN_STATE_DISCONNECT);break;default:break;}}};}
打印操作
//打印切刀命令byte[] bytes={29,86,0};//实时状态查询byte[] bytes1={16,4,2};
private void sendReceiptWithResponse() {EscCommand esc = new EscCommand();esc.addInitializePrinter();esc.addPrintAndFeedLines((byte) 1);// 设置打印居中esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);// 设置为倍高倍宽esc.addText(\"\"+AppApplication.getInstance().getDaoSession().getBusinessSettingDao().loadAll().get(0).getPRINTTITLE()+\"\\n\");esc.addText(\"[商户存根]\\n\");esc.addPrintAndLineFeed();// 设置打印左对齐esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);// 打印文字esc.addText(\"----------------------------\\n\");// 打印文字esc.addText(\"商户号: \"+AppApplication.getInstance().getDaoSession().getDeviceInfoDao().loadAll().get(0).getStoreNum()+\"\\n\");esc.addText(\"商户名称: \"+AppApplication.getInstance().getDaoSession().getDeviceInfoDao().loadAll().get(0).getStoreName()+\"\\n\");esc.addText(\"员工卡号: \"+businessDetail.getWiegand_id()+\"\\n\");esc.addText(\"交易账号: \"+businessDetail.getCARDNUM()+\"\\n\");esc.addText(\"交易类型: \"+businessDetail.getTYPE()+\"\\n\");esc.addText(\"订单号: \"+businessDetail.getORDERNUM()+\"\\n\");esc.addText(\"日期时间: \"+businessDetail.getDATE()+\"\\n\");if (businessDetail.getTYPE().equals(\"消费\")){esc.addText(\"交易金额: RMB \"+businessDetail.getMONEY()+\"\\n\");}else {esc.addText(\"交易金额: RMB -\"+businessDetail.getMONEY()+\"\\n\");}esc.addText(\"----------------------------\\n\");esc.addText(\"备注\\n\");esc.addPrintAndLineFeed();esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);// 开钱箱esc.addGeneratePlus(LabelCommand.FOOT.F5, (byte) 255, (byte) 255);esc.addPrintAndFeedLines((byte) 8);// 加入查询打印机状态,用于连续打印esc.addUserCommand(bytes);Vector<Byte> datas = esc.getCommand();// 发送数据DeviceConnFactoryManager.getDeviceConnFactoryManagers()[0].sendDataImmediately(datas);if(Integer.valueOf(AppApplication.getInstance().getDaoSession().getBusinessSettingDao().loadAll().get(0).getPRINTPAGE())>1){sendReceiptWithResponse1();}}