USB host 通信

公司主打支付产品,产品是和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>

然后再res文件夹下创建一个device_filter.xml文件如下 :

<?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);
			}		
		
		}	
	}

二:找到智能卡接口(UsbInterface)并找到此接口中的输入,输出等端口(UsbEndpoint)

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



关于usb host通信说的比较详细的blog系列:http://www.cnblogs.com/sowhat4999/p/4439877.html






你可能感兴趣的:(USB host 通信)