码迷,mamicode.com
首页 > 移动开发 > 详细

Android pad 连接蓝牙打印机Gprinter---实现蓝牙打印功能

时间:2016-08-30 00:37:29      阅读:892      评论:0      收藏:0      [点我收藏+]

标签:

一、概述

最近的一个项目有一个需求,要求通过pad的蓝牙去连接l蓝牙打印机去打印单据,就是点击一个按钮去触发生成单据>>保存到数据库

>>蓝牙打印。首先想要实现蓝牙连接,然后去调用Gprinter的SDK,在这里我使用的是Gprinter SDK2.1的版本,而SDK2.2与SDK2.1

API有不同的地方,这里就以SDK2.1为例。

二、使用

1、首先要导入jar包、添加依赖,如果没有SDK2.1的版本可以去http://download.csdn.net/download/zabio/9382570下载,

我这里用的是Eclipse。

技术分享

2、添加权限

     <!-- 管理蓝牙设备的权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- 使用蓝牙设备的权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />

  <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

3、在AndroidManifest.xml文件中注册打印服务

        <service
            android:name="com.gprinter.service.GpPrintService"
            android:label="GpPrintService"
            android:process=":remote"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.gprinter.aidl.GpPrintService" />
            </intent-filter>
        </service> 

4 新建包名为com.gprinter.aidl,向包中添加GpService.aidl文件,代码如下:

package com.gprinter.aidl;
	interface GpService{  
    		int openPort(int PrinterId,int PortType,String DeviceName,int PortNumber);
   		void closePort(int PrinterId);
    		int getPrinterConnectStatus(int PrinterId);
    		int printeTestPage(int PrinterId);   
   	 	int queryPrinterStatus(int PrinterId,int Timesout);
   		int getPrinterCommandType(int PrinterId);
    		int sendEscCommand(int PrinterId, String b64);
    		int sendTscCommand(int PrinterId, String  b64); 
	}




5、在onCreate初始化方法里面启动并绑定服务,我这里是Fragment,所以用的Context。

技术分享

//变量我放这里了,如有错误,自己修改

	private int					connectState;	
	private String                                  deviceAddress;//蓝牙mac地址
	private BluetoothSocket                         socket;//蓝牙socket
	private ConnectThread                       mThread;//连接的蓝牙线程
	private MyBroadcastReceiver   	                  receiver;//蓝牙搜索的广播
	private GpService				mGpService	= null;
	private PrinterServiceConnection		mConn		= null;
	private BluetoothAdapter			adapter;//蓝牙适配器
	private BluetoothDevice                         mBluetoothDevice; //蓝牙设备      

	private void startService() {
		Intent i = new Intent(mContext, GpPrintService.class);
		mContext.startService(i);
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public void connection() {
		mConn = new PrinterServiceConnection();
		Intent intent = new Intent("com.gprinter.aidl.GpPrintService");
		intent.setPackage(mContext.getPackageName());
		mContext.bindService(intent, mConn, Context.BIND_AUTO_CREATE); // bindService
	}

	class PrinterServiceConnection implements ServiceConnection {
		@Override
		public void onServiceDisconnected(ComponentName name) {
			Logger.e("ServiceConnection", "onServiceDisconnected() called");
			mGpService = null;
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			Logger.e("ServiceConnection", "onServiceConnected() called");
			mGpService = GpService.Stub.asInterface(service);
		}
	};

连接蓝牙,由于是第一次使用蓝牙去调用打印,这里只说明我自己的方法,取消配对的对话框不一定成功。
	public void searchBlueToothDevice() {
		// 检查设备是否支持蓝牙
		adapter = BluetoothAdapter.getDefaultAdapter();

		if (adapter == null) {
			// 设备不支持蓝牙
			Toast.makeText(mContext,"Your device doesn't support BlueTooth",0).show();

			return;
		}

		// 如果蓝牙已经关闭就打开蓝牙
		if (!adapter.isEnabled()) {
			Logger.e(TAG, "device close");
			
			Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
			return;
		}


		// 获取已配对的蓝牙设备
		Set<BluetoothDevice> devices = adapter.getBondedDevices();

		// 遍历
		int count = 0;

		for (BluetoothDevice pairedDevice : devices) {
			if (pairedDevice.getName() == null) {
				return;
			} else if (pairedDevice.getName().startsWith("Gprinter")) {
				count++;
				deviceAddress = pairedDevice.getAddress();

				//赋值为全局变量
				mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);

				//连接蓝牙
				connect(deviceAddress, mBluetoothDevice);

				break;
			}
		}


		// count=0,说明没有配对,搜索设备
		if (adapter.isEnabled() && count == 0) {
			adapter.startDiscovery();

			if (receiver != null) {
				mContext.unregisterReceiver(receiver);
				receiver = null;
			}


			// 设置广播信息过滤
			IntentFilter intentFilter = new IntentFilter();
			intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
			intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
			intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
			intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
			intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);


			if (receiver == null) {
				receiver = new MyBroadcastReceiver();
				// 注册广播接收器,接收并处理搜索结果
				mContext.registerReceiver(receiver, intentFilter);
			}
		}
	}
	public class MyBroadcastReceiver extends BroadcastReceiver {


		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				if (device == null) {
					return;
				}


				if (device.getName() == null) {
					return;
				}
				if (device.getName().startsWith("Gprinter")) {
					deviceAddress = device.getAddress();
					Logger.e(TAG, device.getName() + "---ACTION_FOUND");

					adapter.cancelDiscovery();
					mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);

					connectState = device.getBondState();
					switch (connectState) {
					// 未配对
					case BluetoothDevice.BOND_NONE:
						// 配对
						try {
							setPin(mBluetoothDevice.getClass(), mBluetoothDevice, "0000");
							Method createBondMethod = mBluetoothDevice.getClass().getMethod("createBond");
							createBondMethod.invoke(mBluetoothDevice);
							cancelPairingUserInput(mBluetoothDevice.getClass(), mBluetoothDevice);
						} catch (Exception e) {
							e.printStackTrace();
						}
						break;
					// 已配对
					case BluetoothDevice.BOND_BONDED:
						 if (device.getName().startsWith("Gprinter")) {
							connect(deviceAddress, mBluetoothDevice);
						}
						break;
					}
				}


			} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {


				// 状态改变的广播
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				if (device.getName() == null) {
					return;
				}
				if (device.getName().startsWith("Gprinter")) {
					deviceAddress = device.getAddress();
					Logger.e(TAG, device.getName() + "---ACTION_BOND_STATE_CHANGED");
					mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
					connectState = device.getBondState();
					switch (connectState) {
					case BluetoothDevice.BOND_NONE:
						break;
					case BluetoothDevice.BOND_BONDING:
						break;
					case BluetoothDevice.BOND_BONDED:
						if (device.getName().startsWith("Gprinter")) {
							connect(deviceAddress, mBluetoothDevice);
						}
						break;
					}
				}


			}
		}
	}


	@SuppressWarnings({ "rawtypes", "unchecked" })
	public boolean setPin(Class btClass, BluetoothDevice btDevice, String str) throws Exception {
		try {
			Method removeBondMethod = btClass.getDeclaredMethod("setPin", new Class[] { byte[].class });
			Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[] { str.getBytes() });
			Log.e("returnValue", "" + returnValue);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
	}


	// 取消用户输入		
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean cancelPairingUserInput(Class btClass, BluetoothDevice device) throws Exception {
		Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
		// cancelBondProcess()
		Boolean returnValue = (Boolean) createBondMethod.invoke(device);
		return returnValue.booleanValue();
	}
	/**
	 * 启动连接蓝牙的线程方法
	 * 
	 * @param macAddress
	 * @param device
	 */
	public synchronized void connect(String macAddress, BluetoothDevice device) {
		if (mThread != null) {
			mThread.interrupt();
			mThread = null;
		}


		if (socket != null) {
			try {
				mGpService.closePort(0);
			} catch (Exception e) {
				e.printStackTrace();
			}
			socket = null;
		}
		mThread = new ConnectThread(macAddress, device);
		mThread.start();
	}

	private class ConnectThread extends Thread {
		private BluetoothDevice	mmDevice;
		private OutputStream	mmOutStream;


		public ConnectThread(String mac, BluetoothDevice device) {
			mmDevice = device;
			String SPP_UUID = "00001101-0000-1000-8000-00805f9b34fb";
			try {
				if (socket == null) {
					socket = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
				}


			} catch (Exception e) {
				e.printStackTrace();
			}
		}


		public void run() {
			// Cancel discovery because it will slow down the connection
			adapter.cancelDiscovery();

			try {
				// Connect the device through the socket. This will block
				// until it succeeds or throws an exception
				Logger.e(TAG, "连接socket");
				if (socket.isConnected()) {
					Logger.e(TAG, "已经连接过了");
				} else {
					// socket.connect();
					if (socket != null) {
						try {
							Logger.e(TAG, mGpService + "--1--" + mBluetoothDevice);
							if (mGpService != null) {
								int state = mGpService.getPrinterConnectStatus(0);
								switch (state) {
								case GpDevice.STATE_CONNECTED:
									break;
								case GpDevice.STATE_LISTEN:
									Logger.e(TAG, "state:STATE_LISTEN");
									break;
								case GpDevice.STATE_CONNECTING:
									Logger.e(TAG, "state:STATE_CONNECTING");
									break;
								case GpDevice.STATE_NONE:
									Logger.e(TAG, "state:STATE_NONE");
									registerBroadcast();
									mGpService.openPort(0, 4, mBluetoothDevice.getAddress(), 0);
									break;


								default:
									Logger.e(TAG, "state:default");
									break;
								}


							} else {
								Logger.e(TAG, "mGpService IS NULL");
							}


							//
						} catch (Exception e) {
							e.printStackTrace();
						}


						// connectToPrinter();
					}
				}


			} catch (Exception connectException) {
				// Unable to connect; close the socket and get out
				Logger.e(TAG, "Unable to connect");
				try {
					if (socket != null) {
						mGpService.closePort(0);
						socket = null;
						// CommonUtils.showToast(mContext, "failed to connect");
					}
				} catch (Exception closeException) {
					// failed to close socket
				}
				return;
			}
		}
	}

	public static final String	ACTION_CONNECT_STATUS	= "action.connect.status";
	private void registerBroadcast() {
		IntentFilter filter = new IntentFilter();
		filter.addAction(ACTION_CONNECT_STATUS);
		mContext.registerReceiver(printerStatusBroadcastReceiver, filter);
	}

	private BroadcastReceiver	printerStatusBroadcastReceiver	= new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
																			if (ACTION_CONNECT_STATUS.equals(intent.getAction())) {
																			int type = intent.getIntExtra(GpPrintService.CONNECT_STATUS, 0);
																			int id = intent.getIntExtra(GpPrintService.PRINTER_ID, 0);
																			if (type == GpDevice.STATE_CONNECTING) {
																				Logger.e(TAG, "STATE_CONNECTING");


																			} else if (type == GpDevice.STATE_NONE) {
																				Logger.e(TAG, "STATE_NONE");
																			} else if (type == GpDevice.STATE_VALID_PRINTER) {
																				Logger.e(TAG, "STATE_VALID_PRINTER");
																			} else if (type == GpDevice.STATE_INVALID_PRINTER) {
																				Logger.e(TAG, "STATE_INVALID_PRINTER");
																			} else if (type == GpDevice.STATE_CONNECTED) {
																				Logger.e(TAG, "STATE_CONNECTED");
																				mContext.unregisterReceiver(printerStatusBroadcastReceiver);
																				getPrinterStatusClicked(id);
																			} else if (type == GpDevice.STATE_LISTEN) {
																				Logger.e(TAG, "STATE_LISTEN");
																			}
																		}
	
	public void getPrinterStatusClicked(int id) {
		try {
			int status = mGpService.queryPrinterStatus(0, 500);
			String str = new String();
			if (status == GpCom.STATE_NO_ERR) {
				str = "打印机正常";
				int state = mGpService.getPrinterCommandType(0);
				if (state == GpCom.ESC_COMMAND) {
					printData();
				} else {
				}
			} else if ((byte) (status & GpCom.STATE_OFFLINE) > 0) {
				str = "The printer is out of service,please try again!";
			} else if ((byte) (status & GpCom.STATE_PAPER_ERR) > 0) {
				str = "There is no Pager in the Printer!";
			} else if ((byte) (status & GpCom.STATE_COVER_OPEN) > 0) {
				str = "The cover of the printer is not closed!";
			} else if ((byte) (status & GpCom.STATE_ERR_OCCURS) > 0) {
				str = "The printer made a mistake!";
			}
			Toast.makeText(mContext, "打印机:" + '0' + " 状态:" + str, Toast.LENGTH_SHORT).show();
		} catch (RemoteException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	} 


7、printData()方法里的内容,参考如下:

技术分享

技术分享


技术分享

技术分享

8、关键代码是sendEscConmand方法的调用,不过SDK2.1打印条形码的长度有限制,所以可以自己生成我一维码图片让后去打

印: com.google.zxing包的一维码打印,导入jar包:可以网上下载

private Bitmap getCodeBitMap(String str) {

		int size = str.length();

		for (int i = 0; i < size; i++) {

			int c = str.charAt(i);

			if ((19968 <= c && c < 40623)) {

				// Toast.makeText(CreateCodeActivity.this, "生成条形码的时刻不能是中文", Toast.LENGTH_SHORT).show();
				return null;

			}

		}

		Bitmap bmp = null;

		try {

			if (str != null && !"".equals(str)) {

				bmp = CreateOneDCode(str);

			}

		} catch (WriterException e) {


			e.printStackTrace();


		}
		return bmp;
	}


	/**
	 * 用于将给定的内容生成成一维码 注:目前生成内容为中文的话将直接报错,要修改底层jar包的内容
	 * 
	 * @param content
	 *            将要生成一维码的内容
	 * 
	 * @return 返回生成好的一维码bitmap
	 * @throws WriterException
	 *             WriterException异常
	 */


	public Bitmap CreateOneDCode(String content) throws WriterException {

		// 生成一维条码,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败


		BitMatrix matrix = null;

		matrix = new MultiFormatWriter().encode(content,

		BarcodeFormat.CODE_128, 260, 90);

		int width = matrix.getWidth();

		int height = matrix.getHeight();

		int[] pixels = new int[width * height];

		for (int y = 0; y < height; y++) {

			for (int x = 0; x < width; x++) {

				if (matrix.get(x, y)) {
					pixels[y * width + x] = mContext.getResources().getColor(R.color.black);
				} else {
					pixels[y * width + x] = mContext.getResources().getColor(R.color.white);	;
				}


			}


		}


		Bitmap bitmap = Bitmap.createBitmap(width, height,


		Bitmap.Config.ARGB_8888);


		// 通过像素数组生成bitmap,具体参考api


		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

		return bitmap;

	}



9、打印的条形码要传入一个字符串--我这里是实体类里的一个字段

技术分享

三、后语

第一次写博客,可能会存在一些问题,望大家见谅·如果有不懂的可以留言。




Android pad 连接蓝牙打印机Gprinter---实现蓝牙打印功能

标签:

原文地址:http://blog.csdn.net/algerhf/article/details/52240212

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!