标签:
最近的一个项目有一个需求,要求通过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