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