技术分享
记录踩过的坑和别的大佬没有叽歪的点
开始做蓝牙打印看到网上很多做混合开发 和安卓开发,ios开发的例子,插件等等版本大同小异,并不是像其他博客上所说的那么简单,[下载插件,无需改动,连接打印开始,图片为证],没那么简单.往往困扰我们没有进行下去的是细节,那么
为了能让小伙伴们少走弯路我来分享一下吧,
这个插件很多 随便下载一个 列表,连接,打印 断连 这四个功能
蓝牙打印插件下载
插件放在 软件 目录 WeX5_V3.8\model\Native\plugins 下
插件内java文件可以手动修改 根据自己的需要, 有的需要 改写蓝牙连接功能, new一个线程去连接,我这里没有new,连接需要时间, 可能会报错 read failed,socket might closed or timeout,read ret:-1
java
package cordova.plugin.bluetooth.printer;import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Set;
import java.util.UUID;import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;import android.content.Context;public class BluetoothPrinter extends CordovaPlugin {private static final String LOG_TAG = "BluetoothPrinter";BluetoothAdapter mBluetoothAdapter;BluetoothSocket mmSocket;BluetoothDevice mmDevice;OutputStream mmOutputStream;InputStream mmInputStream;Thread workerThread;byte[] readBuffer;int readBufferPosition;int counter;volatile boolean stopWorker;public BluetoothPrinter() {}@Overridepublic boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {if (action.equals("list")) {listBT(callbackContext);////return true;} else if (action.equals("connect")) {String name = args.getString(0);if (findBT(callbackContext, name)) {try {connectBT(callbackContext);} catch (IOException e) {Log.e(LOG_TAG, e.getMessage());e.printStackTrace();}} else {callbackContext.error("Bluetooth Device Not Found: " + name);}return true;} else if (action.equals("disconnect")) {try {disconnectBT(callbackContext);} catch (IOException e) {Log.e(LOG_TAG, e.getMessage());e.printStackTrace();}return true;}else if (action.equals("print")) {try {String msg = args.getString(0);print(callbackContext, msg);} catch (IOException e) {Log.e(LOG_TAG, e.getMessage());e.printStackTrace();}return true;}else if (action.equals("printPOSCommand")) {try {String msg = args.getString(0);printPOSCommand(callbackContext, hexStringToBytes(msg));} catch (IOException e) {Log.e(LOG_TAG, e.getMessage());e.printStackTrace();}return true;}return false;}//This will return the array list of paired bluetooth printersvoid listBT(CallbackContext callbackContext) {BluetoothAdapter mBluetoothAdapter = null;String errMsg = null;try {mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {errMsg = "No bluetooth adapter available";Log.e(LOG_TAG, errMsg);callbackContext.error(errMsg);return;}if (!mBluetoothAdapter.isEnabled()) {Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);this.cordova.getActivity().startActivityForResult(enableBluetooth, 0);}Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();if (pairedDevices.size() > 0) {JSONArray json = new JSONArray();for (BluetoothDevice device : pairedDevices) {/*Hashtable map = new Hashtable();map.put("type", device.getType());map.put("address", device.getAddress());map.put("name", device.getName());JSONObject jObj = new JSONObject(map);*/json.put(device.getName());}callbackContext.success(json);} else {callbackContext.error("No Bluetooth Device Found");}//Log.d(LOG_TAG, "Bluetooth Device Found: " + mmDevice.getName());} catch (Exception e) {errMsg = e.getMessage();Log.e(LOG_TAG, errMsg);e.printStackTrace();callbackContext.error(errMsg);}}// This will find a bluetooth printer deviceboolean findBT(CallbackContext callbackContext, String name) {try {mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {Log.e(LOG_TAG, "No bluetooth adapter available");}if (!mBluetoothAdapter.isEnabled()) {Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);this.cordova.getActivity().startActivityForResult(enableBluetooth, 0);}Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();if (pairedDevices.size() > 0) {for (BluetoothDevice device : pairedDevices) {if (device.getName().equalsIgnoreCase(name)) {mmDevice = device;return true;}}}Log.d(LOG_TAG, "Bluetooth Device Found: " + mmDevice.getName());} catch (Exception e) {String errMsg = e.getMessage();Log.e(LOG_TAG, errMsg);e.printStackTrace();callbackContext.error(errMsg);}return false;}// Tries to open a connection to the bluetooth printer deviceboolean connectBT(CallbackContext callbackContext) throws IOException {try {// Standard SerialPortService IDUUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);//String cmd="Qsprinter";//PrintService.pl.connect(cmd);mmSocket.connect();mmOutputStream = mmSocket.getOutputStream();mmInputStream = mmSocket.getInputStream();beginListenForData();//Log.d(LOG_TAG, "Bluetooth Opened: " + mmDevice.getName());callbackContext.success("Bluetooth Opened: " + mmDevice.getName());//callbackContext.success("Bluetooth Opened: " + "ceshi_shebei");return true;} catch (Exception e) {String errMsg = e.getMessage();Log.e(LOG_TAG, errMsg);e.printStackTrace();callbackContext.error(errMsg);}return false;}// After opening a connection to bluetooth printer device, // we have to listen and check if a data were sent to be printed.void beginListenForData() {try {final Handler handler = new Handler();// This is the ASCII code for a newline characterfinal byte delimiter = 10;stopWorker = false;readBufferPosition = 0;readBuffer = new byte[1024];workerThread = new Thread(new Runnable() {public void run() {while (!Thread.currentThread().isInterrupted() && !stopWorker) {try {int bytesAvailable = mmInputStream.available();if (bytesAvailable > 0) {byte[] packetBytes = new byte[bytesAvailable];mmInputStream.read(packetBytes);for (int i = 0; i < bytesAvailable; i++) {byte b = packetBytes[i];if (b == delimiter) {byte[] encodedBytes = new byte[readBufferPosition];System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);/*final String data = new String(encodedBytes, "US-ASCII");readBufferPosition = 0;handler.post(new Runnable() {public void run() {myLabel.setText(data);}});*/} else {readBuffer[readBufferPosition++] = b;}}}} catch (IOException ex) {stopWorker = true;}}}});workerThread.start();} catch (NullPointerException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}//This will send data to bluetooth printerboolean print(CallbackContext callbackContext, String msg) throws IOException {try {//mmOutputStream.write(new byte[] { 0x1b, 0x74,0x15 });//后添加//mmOutputStream.write(msg.getBytes());mmOutputStream.write(msg.getBytes("GBK"));//防止中文打印乱码//mmOutputStream.write(new byte[] { 0x1d, 0x0c });//后添加/*String message="20160825888";if (message.length() > 0) {byte[] btdata=null;try {btdata=message.getBytes("ASCII");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}//Enable the barcodemmOutputStream.write(new byte[]{0x1d,0x45,0x43,0x01});//Set the barcode height is 162mmOutputStream.write(new byte[]{0x1d,0x68,(byte) 0xa2});//Set HRI character print location on bottommmOutputStream.write(new byte[]{0x1d,0x48,0x02});mmOutputStream.write(new byte[]{0x1d,0x77,0x02});//Print the barcode use code128byte[] qrHead=new byte[]{0x1d,0x6b,0x49,(byte) btdata.length};
// byte[] qrHead=new byte[]{0x1d,0x6b,0x44,(byte) btdata.length};byte[] barCodeData=new byte[qrHead.length+btdata.length];System.arraycopy(qrHead, 0, barCodeData, 0, qrHead.length);System.arraycopy(btdata, 0, barCodeData, qrHead.length, btdata.length);mmOutputStream.write(barCodeData);mmOutputStream.write(new byte[] { 0x1d, 0x0c });//mmOutputStream.printText("\r\n");// Bitmap btMap = BarcodeCreater.creatBarcode(PrintBarCodeActivity.this,
// message, 384, 100, true, 1);
// PrintService.pl.printImage(btMap);
// PrintService.pl.write(new byte[] { 0x1d, 0x0c });}//结束*///mmOutputStream.write(new byte[] { 0x1b, 0x74,0x15 });////mmOutputStream.write(msg.getBytes("UTF-8"));//mmOutputStream.write(new byte[] { 0x1d, 0x0c });///*mmOutputStream.write(new byte[] { 0x1b, 0x74,0x15 });////mmOutputStream.write(msg.getBytes());mmOutputStream.write(msg.getBytes("GBK"));//防止中文打印乱码mmOutputStream.write(new byte[] { 0x1d, 0x0c });//*/// tell the user data were sent//Log.d(LOG_TAG, "Data Sent");callbackContext.success("Data Sent success");return true;} catch (Exception e) {String errMsg = e.getMessage();Log.e(LOG_TAG, errMsg);e.printStackTrace();callbackContext.error(errMsg);}return false;}boolean printPOSCommand(CallbackContext callbackContext, byte[] buffer) throws IOException {try {mmOutputStream.write(buffer);// tell the user data were sentLog.d(LOG_TAG, "Data Sent");callbackContext.success("Data Sent");return true;} catch (Exception e) {String errMsg = e.getMessage();Log.e(LOG_TAG, errMsg);e.printStackTrace();callbackContext.error(errMsg);}return false;}// disconnect bluetooth printer.boolean disconnectBT(CallbackContext callbackContext) throws IOException {try {stopWorker = true;mmOutputStream.close();mmInputStream.close();mmSocket.close();callbackContext.success("Bluetooth Disconnect");return true;} catch (Exception e) {String errMsg = e.getMessage();Log.e(LOG_TAG, errMsg);e.printStackTrace();callbackContext.error(errMsg);}return false;}public byte[] getText(String textStr) {// TODO Auto-generated method stubbyte[] send;byte[] send=null;try {send = textStr.getBytes("GBK");} catch (UnsupportedEncodingException e) {send = textStr.getBytes();}return send;}public static byte[] hexStringToBytes(String hexString) {hexString = hexString.toLowerCase();String[] hexStrings = hexString.split(" ");byte[] bytes = new byte[hexStrings.length];for (int i = 0; i < hexStrings.length; i++) {char[] hexChars = hexStrings[i].toCharArray();bytes[i] = (byte) (charToByte(hexChars[0]) << 4 | charToByte(hexChars[1]));}return bytes;}private static byte charToByte(char c) {return (byte) "0123456789abcdef".indexOf(c);}}
js
var exec = require('cordova/exec');var BTPrinter = {list: function(fnSuccess, fnError){exec(fnSuccess, fnError, "BluetoothPrinter", "list", []);},connect: function(fnSuccess, fnError, name){exec(fnSuccess, fnError, "BluetoothPrinter", "connect", [name]);},disconnect: function(fnSuccess, fnError){exec(fnSuccess, fnError, "BluetoothPrinter", "disconnect", []);},print: function(fnSuccess, fnError, str){exec(fnSuccess, fnError, "BluetoothPrinter", "print", [str]);},printPOSCommand: function(fnSuccess, fnError, str){exec(fnSuccess, fnError, "BluetoothPrinter", "printPOSCommand", [str]);}
};module.exports = BTPrinter;
示例下载
示例下载
//蓝牙打印Model.prototype.btClick = function(event){debugger;var strCmd1 = "T 12 2 0 10 12号字体测试\n";//文本var strCmd2 = addCPCLQRCode(0,40,'M', 2, 5, "12号中文字二维码测试");//二维码 var strCmd3 = addCPCLBarCode(150,10,'128',50,0,1,1,'123456');//条形码var strCmd4 = "T 12 2 180 70 123456\n";//文本var byte2 = "! 0 200 200 300 1\n" //这是开始代码+strCmd1+strCmd2+strCmd3+strCmd4+"PRINT\n";//这是结束代码//蓝牙打印if( this.blueConect) {var packageID = this.packageID;BTPrinter.print ( function (data){console.log ( "success" ) ;console.log (packageID) ;alert (data) ;},function(err){console.log ( "Error") ;console.log (err);alert (err) ;}, byte2);}};
最后说几个问题
图一
连接蓝牙之前需要用手机的蓝牙模块先连接蓝牙打印机 点击蓝牙列表>> 蓝牙连接(3秒左右会连接成功)>>打印
用手机连接蓝牙时也是我被坑的地方这个手没有出现 ble_name,但是不影响我阐述, 看图4图5 打印机有两个蓝牙信号 一个name[打印机信号名] 一个ble_name[打印机蓝牙信号名]
咱不知道为啥要两个 看图标一个是蓝牙标识,一个是打印机标识 两个名字只差一个L字母 开始我连接的是 带L的信号(蓝牙信号),不用配对密码可以直接连接,打印机也会显示连接成功的信号,
所以没在意一直以为是程序问题 功能上只有列表可以用,连接 打印都无法使用,就是因为当初输了1234没成功所以固执的认为这个是给配对用的参考,就没有输入0000,
其实0000才是配对密码,打印不需要输入配对是默认的,只要在手机一方输入即可配对成功,后来才知道要用带打印机图标的信号,程序没有问题,是信号选择的问题.每一个细节都肯能困扰你打印失败,让你排错的方向走叉
总结一下,1插件名错误,
2,修改插件要重新编译打包
3.cordova 基本插件引入
4.测试最好单开app 减少干扰项,后期排错方便
5.打印机说明书
6.打印机信号都试试
7.UI2 打包 网络 网速影响app
8.打印纸安装
9.打印距离
10.手机版本4.2以上.
11.蓝牙打印机蓝牙低功耗4.0以上
记着的就这么多,有问题的可以留言,其实功能很简单无非是一些细节没有控制好,知道了就简单的一逼
祝你们好运