关于Android usb host 总结

前段时间因为项目需要,做了一段时间关于Android USB Host的开发,最近闲下来总结一下。

Android模拟器无法测试USB,大部分的平板都不能使用usb host api,这里使用的测试平板是华硕的TF101,有一款可以测试Android平板是否支持USB HostAPI的apk http://download.csdn.net/download/limitemp/4837706

使用usb host api的使用步骤:

注册广播:

AndroidManifest.xml
       ...>
...
    
         android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    

     android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/device_filter" />
device_filter.xml
xml version="1.0" encoding="utf-8"?>


     vendor-id="1234" product-id="5678" />

代码中:

BroadcastReceiver mUsbReceiver= new BroadcastReceiver() {
    public void onReceive(Context context,Intent intent){
        String action = intent.getAction();

      if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)){
            UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            if (device!= null){
                // call your method that cleans up and closescommunication with the device
            }
        }
    }
};

 

上面的语句主要是为了向系统注册广播,当有USB设备插入的时候系统会弹出提示,如:


vendor-idproduct-id是需要提示的usb设备的两个属性,这些属性可是使用一些USB查看工具来获取,xp下有一个USBtrace挺好用。如果这里什么都不写,则表示对于任何插入的USB设备都会有提示(其实并非任何例如键盘鼠标这类的HID设备就会提示)。

1.  获取UsbManager:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

2.  获取设备列表:

HashMap<String, UsbDevice> deviceList = manager.getDeviceList();

3.  通过UsbDevice来获得USBInterface:

UsbInterface getInterface(int index);

获取Interface以后可以根据其类型判断该USB设备的类型

Int getInterfaceClass();返回值为Int类型可以在UsbConstants类中找到对应的值例如:

public static final intUSB_CLASS_AUDIO

USB class for audio devices.

Constant Value: 1 (0x00000001)

该设备为audio设备,int值为1;

4.   根据获得的Interface获取Endpoint:

Endpoint的传输方向有两种,一种是In,一种是Out;对于Android为Host模式来说,in就是传向Host设备的,out是传向Device的;同时Endpoint分为四种类型:USB_ENDPOINT_XFER_CONTROL (endpoint zero)

USB_ENDPOINT_XFER_ISOC (isochronousendpoint)

USB_ENDPOINT_XFER_BULK (bulkendpoint)

USB_ENDPOINT_XFER_INT (interruptendpoint)

分别为对应四种不同的传输类型:控制传输,实时传输,批量传输,中断传输。

根据不同的传输类型选择不同的方法去传输数据。在UsbRequest中有这样一段话:

UsbRequests can beused to transfer data on bulk and interrupt endpoints. Requests on bulkendpoints can be sent synchronously via bulkTransfer(UsbEndpoint, byte[],int, int) or asynchronously via queue(ByteBuffer, int) and requestWait().Requests on interrupt endpoints are only send and received asynchronously.

Requests onendpoint zero are not supported by this class; use controlTransfer(int,int, int, int, byte[], int, int) for endpoint zero requests instead.

就是说对于bulkendpoint可是使用bulkTransfer方法同步传输或者使用queue和requestWait方法异步传输,但是对于interrupt endpoint使用Request只能进行异步传输。而对于endpoint zero端口只能使用controlTransfer方法。所以要根据自己的端口类型来选择合适的方法来传输,否则可能接收不到数据。

例如使用的USB设备的端口类型为bulk endpoint所以直接使用bulkTransfer方法就行了。过程如下:
UsbDeviceConnection connection = mUsbManager.openDevice(device);

//device 为你要打开的设备,这里涉及权限的问题,下面再说
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT)

//endpoint如果要接收数据就选择In端口,发送数据选择Out端口,同事这个方法是个阻塞式的方法,所以应该放到其他的线程中。

5.  关于UsbDeviceConnection connection = mUsbManager.openDevice(device);权限的问题:

SDK中有说明,如果设备是通过系统广播的形式获得,则不需要权限就可以直接打开。如果设备是通过manager.getDeviceList();枚举的方式获得,则在打开设备的时候需要权限。SDK中有这样一段代码:

UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
private staticfinal String ACTION_USB_PERMISSION=
    "com.android.example.USB_PERMISSION";
...
mPermissionIntent = PendingIntent.getBroadcast(this,0, new Intent(ACTION_USB_PERMISSION),0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

当运行到openDevice()时,系统会检查应用程序是否存在权限,若没有则会弹出用户授权的对话框。同意则打开成功,否则失败提示没有权限。

你可能感兴趣的:(Android)