技术分享
记录踩过的坑和别的大佬没有叽歪的点
开始做蓝牙打印看到网上很多做混合开发 和安卓开发,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() {}
@Override
public 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 printers
void 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 device
boolean 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 device
boolean connectBT(CallbackContext callbackContext) throws IOException {
try {
// Standard SerialPortService ID
UUID 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 character
final 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 printer
boolean 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 block
e.printStackTrace();
}
//Enable the barcode
mmOutputStream.write(new byte[]{0x1d,0x45,0x43,0x01});
//Set the barcode height is 162
mmOutputStream.write(new byte[]{0x1d,0x68,(byte) 0xa2});
//Set HRI character print location on bottom
mmOutputStream.write(new byte[]{0x1d,0x48,0x02});
mmOutputStream.write(new byte[]{0x1d,0x77,0x02});
//Print the barcode use code128
byte[] 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 sent
Log.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秒左右会连接成功)>>打印
2
用手机连接蓝牙时也是我被坑的地方这个手没有出现 ble_name,但是不影响我阐述, 看图4图5 打印机有两个蓝牙信号
咱不知道为啥要两个 看图标一个是蓝牙标识,一个是打印机标识 两个名字只差一个L字母 开始我连接的是 带L的信号(蓝牙信号),不用配对密码可以直接连接,打印机也会显示连接成功的信号,
所以没在意一直以为是程序问题 功能上只有列表可以用,连接 打印都无法使用,就是因为当初输了1234没成功所以固执的认为这个是给配对用的参考,就没有输入0000,
其实0000才是配对密码,打印不需要输入配对是默认的,只要在手机一方输入即可配对成功,后来才知道要用带打印机图标的信号,程序没有问题,是信号选择的问题.每一个细节都肯能困扰你打印失败,让你排错的方向走叉
3
4
图5
总结一下,1插件名错误,
2,修改插件要重新编译打包
3.cordova 基本插件引入
4.测试最好单开app 减少干扰项,后期排错方便
5.打印机说明书
6.打印机信号都试试
7.UI2 打包 网络 网速影响app
8.打印纸安装
9.打印距离
10.手机版本4.2以上.
11.蓝牙打印机蓝牙低功耗4.0以上
记着的就这么多,有问题的可以留言,其实功能很简单无非是一些细节没有控制好,知道了就简单的一逼
祝你们好运