公司主打支付产品,产品是和Android平板连接起来的。Android平板怎么和产品通信呢?串口或者USB口。串口通信比较简单,下篇再讲,此篇主要讲的是usb host通信。
一:寻找UsbDevice并授权
两种方法寻找usb device,1是通过Intent Filter来寻找,2是通过枚举所有的设备来寻找
1.在manifest文件中添加如下代码:
<activity ...> ... <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" /> </activity>
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="1411" product-id="22336" /> </resources>然后在包含此 Intent Filter的activity中通过如下方法就可以得到已经授权的USBDevice了
Intent intent = getIntent(); UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);当用户在已经打开此应用的平板中插入产品模块的时候,此activity会自动打开并弹出对话框,“是否授权usb读写权限”,当用户点击“是”时,此应用就会得到应用授权的UsbDevice。
2.通过枚举所有的设备来寻找
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); getUsbDevice(mUsbManager); ...... private void getUsbDevice(UsbManager mUsbManager) { HashMap<String, UsbDevice> devicesList = mUsbManager.getDeviceList(); Iterator<UsbDevice> deviceIterator = devicesList.values().iterator(); while(deviceIterator.hasNext()) { UsbDevice usb = deviceIterator.next(); if(usb.getProductId()==0x5740 && usb.getVendorId()==0x0583) { usbDevice = usb; } } }但是通过此方法寻找出来的usbDevice并没有得到授权,所以需要在此之上进行授权,怎么授权,如下:
mUsbReceiver = new UsbReceiver(); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); registerReceiver(mUsbReceiver, filter); mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); mUsbManager.requestPermission(usbDevice, mPermissionIntent);mUsbManager调用方法
requestPermission()
将弹出对话框,以询问用户是授权应用。广播接收类如下:
private class UsbReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { usbDevice = (UsbDevice) intent .getParcelableExtra(UsbManager.EXTRA_DEVICE); boolean usbPremission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false); if((usbPremission) && (usbDevice != null)) { findEndPoint(); openDevice(localUsbInterface); } else { } } } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { usbDevice = (UsbDevice) intent .getParcelableExtra(UsbManager.EXTRA_DEVICE); if(usbDevice != null) { } else { } if (!mUsbManager.hasPermission(usbDevice)) { mUsbManager.requestPermission(usbDevice, mPermissionIntent); } } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { usbDevice = (UsbDevice) intent .getParcelableExtra(UsbManager.EXTRA_DEVICE); } } }
public void findEndPoint() { int countInterface = usbDevice.getInterfaceCount(); Log.i("kejian","countInterface = "+countInterface); int i=0; int interfaceClass=0; for(i=0;i<countInterface;i++) { localUsbInterface= usbDevice.getInterface(i); interfaceClass=localUsbInterface.getInterfaceClass(); //如果当前接口不是智能卡接口,则不处理 if(interfaceClass!=0x0B) continue; int countEndpoint=localUsbInterface.getEndpointCount(); UsbEndpoint localUsbEndpoint; for(int j=0;j<countEndpoint;j++) { localUsbEndpoint=localUsbInterface.getEndpoint(j); int typeEndpoint=localUsbEndpoint.getType(); // 端点类型为2,批量传输 if(typeEndpoint==2) { if(localUsbEndpoint.getDirection()==0) { //localObject1是输出端点 if(localObject1==null) localObject1=localUsbEndpoint; } else if(localObject2==null) { //localObject2是输入端点 localObject2=localUsbEndpoint; } } else { //端点类型为3,中断方式 if(typeEndpoint!=3) continue; if((localUsbEndpoint.getDirection()!=0x80)||(localObject3!=null)) { continue; } localObject3=localUsbEndpoint; } } } }
public void openDevice(UsbInterface mInterface) { if (mInterface != null) { UsbDeviceConnection conn = null; // 在open前判断是否有连接权限;对于连接权限可以静态分配,也可以动态分配权限 if (mUsbManager.hasPermission(usbDevice)) { conn = mUsbManager.openDevice(usbDevice); } if (conn == null) { return; } if (conn.claimInterface(mInterface, true)) { myDeviceConnection = conn; if (myDeviceConnection != null)// 到此你的android设备已经连上zigbee设备 System.out.println("open设备成功!"); final String mySerial = myDeviceConnection.getSerial(); System.out.println("设备serial number:" + mySerial); } else { System.out.println("无法打开连接通道。"); conn.close(); } } }经过上面这些步骤,接下来就可以进行通信了
Button trans_btn = (Button) this.findViewById(R.id.trans); trans_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub new Thread(new Runnable(){ @Override public void run() { trans(); } }).start(); } });
public void trans() { int status = myDeviceConnection.bulkTransfer((UsbEndpoint)localObject1, USB_CARD_SWING_COMMAND, USB_CARD_SWING_COMMAND.length, 6000); byte []tmpRecv=new byte[2048]; status=myDeviceConnection.bulkTransfer((UsbEndpoint)localObject2,tmpRecv ,tmpRecv.length, 60000); Log.d(TAG,"recv len = "+status); byte []dataReturn=new byte[status]; System.arraycopy(tmpRecv, 0, dataReturn, 0, status); Log.d(TAG,"sendApdu Recv = "+Utils.bytesToHexStr(dataReturn, 0, status)); }第一个bulkTransfer方法是给产品模块发送数据,产品模块对此数据进行处理之后,会返回数据,这里的第二个bulkTransfer方法就是用来接收数据的,根据log信息显示的是正确的返回信息。
参考资料:
http://blog.csdn.net/halsonhe/article/details/46648699
http://blog.csdn.net/wizardmly/article/details/8350137