技术分享

记录踩过的坑和别的大佬没有叽歪的点

开始做蓝牙打印看到网上很多做混合开发 和安卓开发,ios开发的例子,插件等等版本大同小异,并不是像其他博客上所说的那么简单,[下载插件,无需改动,连接打印开始,图片为证],没那么简单.往往困扰我们没有进行下去的是细节,那么

为了能让小伙伴们少走弯路我来分享一下吧,

android开发蓝牙打印 蓝牙打印工具_cordova

这个插件很多 随便下载一个 列表,连接,打印 断连 这四个功能

蓝牙打印插件下载

插件放在  软件 目录 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);
			
			
			
		}
	};

 

 

 

android开发蓝牙打印 蓝牙打印工具_蓝牙_02

android开发蓝牙打印 蓝牙打印工具_wex5_03

 

 

最后说几个问题

图一

android开发蓝牙打印 蓝牙打印工具_android开发蓝牙打印_04

 连接蓝牙之前需要用手机的蓝牙模块先连接蓝牙打印机  点击蓝牙列表>> 蓝牙连接(3秒左右会连接成功)>>打印

android开发蓝牙打印 蓝牙打印工具_打印_05

2

用手机连接蓝牙时也是我被坑的地方这个手没有出现 ble_name,但是不影响我阐述, 看图4图5 打印机有两个蓝牙信号

咱不知道为啥要两个 看图标一个是蓝牙标识,一个是打印机标识 两个名字只差一个L字母 开始我连接的是 带L的信号(蓝牙信号),不用配对密码可以直接连接,打印机也会显示连接成功的信号,

所以没在意一直以为是程序问题 功能上只有列表可以用,连接 打印都无法使用,就是因为当初输了1234没成功所以固执的认为这个是给配对用的参考,就没有输入0000,

其实0000才是配对密码,打印不需要输入配对是默认的,只要在手机一方输入即可配对成功,后来才知道要用带打印机图标的信号,程序没有问题,是信号选择的问题.每一个细节都肯能困扰你打印失败,让你排错的方向走叉


android开发蓝牙打印 蓝牙打印工具_蓝牙_06

3

 


android开发蓝牙打印 蓝牙打印工具_蓝牙_07

4

android开发蓝牙打印 蓝牙打印工具_蓝牙_08

图5

 

总结一下,1插件名错误,

2,修改插件要重新编译打包

3.cordova 基本插件引入

4.测试最好单开app 减少干扰项,后期排错方便

5.打印机说明书

6.打印机信号都试试

7.UI2 打包 网络 网速影响app

8.打印纸安装

9.打印距离

10.手机版本4.2以上.

11.蓝牙打印机蓝牙低功耗4.0以上

记着的就这么多,有问题的可以留言,其实功能很简单无非是一些细节没有控制好,知道了就简单的一逼

祝你们好运