Android下的USB Host介绍和开发

1.USB Host介绍
USB Host,中文意思是USB主模式,是相对于USB Accessory(USB副模式)来说的。如果Android工作在USB Host模式下,则连接到Android上的USB设备把Android类似的看作是一台PC机,PC机能干的事儿,Android也能干,例如将鼠标、键盘插入则可以使用键盘、鼠标来操作Android系统,如果插入U盘则,通过Android可以读写U盘上的数据。而USB Accessory模式表示将Android设备类似当作一个USB的键盘、鼠标、U盘插入到电脑主机上一样使用,这两种模式在Android API level-12以上才支持,即Android3.1及更高的版本支持这两种模式。

2.USB Host模式介绍
2.1 UsbManager

负责管理USB设备的类,你可以在相应代码中通过以下方法获得此对象的一个实例:UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
该类提供的主要方法有:
1) getDeviceList()
获得设备列表,返回的是一个HashMap.;
2) hasPermission(UsbDevice device)
判断你的应用程序是否有接入此USB设备的权限,如果有则返回真,否则返回false.
3) openDevice(UsbDevice device)
打开USB设备,以便向此USB设备发送和接受数据,返回一个关于此USB设备的连接。
4) requestPermission(UsbDevice device, PendingIntent pi)
向USB设备请求临时的接入权限。

2.2 UsbDevice
代表一个USB设备的类,每个设备都包含了一个或多个接口,每个接口又包含一个或多个节点用来与此设备传输数据。该类的主要方法有:
1) getDeviceClass()
返回此USB设备的类别,用一个整型来表示。
2) getDeviceId()
返回唯一标识此设备的ID号,也用一个整型来表示。
3) getDeviceName()
返回此设备的名称,用一个字符串来表示。
4) getDeviceProtocol()
返回此设备的协议类别,用一个整型来表示。
5) getDeviceSubclass()
返回此设备的子类别,用一个整型来表示。
6) getVendorId()
返回生产商ID
7) getProductId()
返回产品ID
8) getInterfaceCount()
返回此设备的接口数量
9) getInterface(int index)
得到此设备的一个接口,返回一个UsbInterface。

2.3UsbInterface
代表USB设备的一个接口,注意:UsbInterface本身是一个类,并不是一个接口。此类的主要方法有以下:
1) getId()
得到给接口的id号。
2) getInterfaceClass()
得到该接口的类别。
3) getInterfaceSubclass()
得到该接口的子类。
4) getInterfaceProtocol()
得到该接口的协议类别。
5) getEndpointCount()
获得关于此接口的节点数量。
6) getEndpoint(int index)
对于指定的index获得此接口的一个节点,返回一个UsbEndpoint.
2.4 UsbEndpoint
代表一个接口的某个节点的类。该类主要提供了一下方法供你使用:
1) getAddress()
获得此节点的地址
2) getAttributes()
获得此节点的属性
3) getDirection()
获得此节点的数据传输方向
2.5 UsbDeviceConnection
代表USB连接的一个类。用此连接可以想USB设备发送和接收数据,可以通过调用该方法openDevice(UsbDevice) 来得到该类的一个实例。该类提供了以下方法供你使用:
1)bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
通过给定的endpoint来进行大量的数据传输,传输的方向取决于该节点的方向,buffer是要发送或接收的字节数组,length是该字节数组的长度。传输成功则返回所传输的字节数组的长度,失败则返回负数。
2)controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
该方法通过0节点向此设备传输数据,传输的方向取决于请求的类别,如果requestType为USB_DIR_OUT则为写数据,USB_DIR_IN, 则为读数据
Android配置文件要求
在你使用以上API进行开发之前,你需要在你的AndroidManifest.xml文件中添加以下内容:
1.因为并不能保证所有的安卓设备都支持以上API,所以你需要声明:
12以下的版本是不支持以上APId的。
 
2.如果你想有一个USB设备接入你的安卓设备时能够通知你的应用程序,那么你需要在你的Activity标签中声明以下内容

< 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" />

Resource属性指定了要过滤的数据设备信息,包括:
1) vendor-id 设备生产商id
2) product-id 设备id
3) class 设备类别
4) subclass 设备子类
5) protocol(device or interface) 协议类别 
device_filter.xml文件放在resxml目录下,其中文件名不包括扩展名部分需要与 标签中声明的一致。示例如下:
<?xml version="1.0" encoding="utf-8"?>


< usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
< /resources>

3. 开发步骤
3.1 检测设备

你的应用可以通过两种方式来发现USB设备,一种是用一个意图过滤器在用户连接一个设备时对其进行通知,另一种则是通过枚举您已经连接的所有USB设备。如果你希望你的应用能够自动的探测到你想要的设备,请使用一个意图过滤器来做。但是,如果你希望得到一个已连接设备的列表或者你不希望过滤意图,枚举所有的设备会是一个更好的选择。
1)Intent Filter
为了让应用可以发现一个特定的USB设备,你可以为android.hardware.usb.action.USB_DEVICE_ATTACHED这个意图指定一个意图来进行过滤。伴随着这个意图过滤器,您需要指定一个资源文件来特别说明这个USB设备的属性,例如供应商和产品ID。当用户连接到一个符合你配件过滤条件的配件时,这个系统会谈出一个对话框询问他们是否希望开始你的应用。如果用户同意,那么你的应用在失去连接之前会自动获取和设备连接的权限。
下面的例子告诉你该如何声明这个意图过滤器:

... 
< intent-filter> 
< action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />  
< meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
< /activity>

下面的例子告诉你怎么样声明指定你希望连接的USB设备的相关资源文件:
<?xml version="1.0" encoding="utf-8"?> 
< resources> 
< usb-device vendor-id="1234" product-id="5678" />
< /resources>
2)列举设备
你可以通过UsbMnanger来列举已经连接的USB设备:代码如下
首先,得到UsbMnanger的一个实例
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
其次,通过此类的getDeviceList()方法得到包含所有已连接的USB设备的列表
HashMap deviceList = manager.getDeviceList();
最后,通过设备名称来得到给设备对象
UsbDevice device = deviceList.get("deviceName");
如果你想一个一个的列举所有的设备,可以实用迭代器,代码实例如下:
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap deviceList = manager.getDeviceList();
Iterator deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next()
//在这里添加处理设备的代码
}
3.2 获得和设备通信的权限
如果你实用intent filter来发现一个USB设备,即上述方法1)那么应用程序可以自动的获取权限;
如果是使用方法2)来检测USB设备,则你需要显示声明权限。其步骤如下:
首先:创建一个广播接收器,接受请求权限的广播,代码如下:
private static final String ACTION_USB_PERMISSION =private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//在这里增加通信的代码
}}}}}};

然后:在你的主Activity中注册该广播接收器,代码如下:
UsbManager mUsbManager= (UsbManager) getSystemService(Context.USB_SERVICE);
private static final 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);
最后,调用此函数 requestPermission() 来显示询问对话框,即在上面红线处添加如下代码:
mUsbManager.requestPermission(device, mPermissionIntent);
3.3 和设备通信
Android设备和一个连接它的USB设备通信即可以是同步的也可以使异步的,不管是那种情况,你都应该创建一个新的线程去负责所有的数据传输,以免阻塞UI线程。为了和US B设备建立通信,你首先需要得到合适的接口和节点,然后通过UsbDeviceConnection在此节点上进行数据的传输,由此你的代码应该:
1)检查该USB设备的属性,例如,生产商id,产品id,设备类别,以确定你是否需要和此设备进行通信。
2)当你确定要和此设备进行通信的时候,找到合适的接口和节点。
3)当你找到一个合适的节点后,用UsbDeviceConnection在此节点上打开连接。
4)使用bulkTransfer()或者controlTransfer() 来发送和接收数据。示例代码如下:
private Byte[] bytes
private static int TIMEOUT= 0;
private boolean forceClaim= true;
...
UsbInterface intf= device.getInterface(0);
UsbEndpoint endpoint= intf.getEndpoint(0);
UsbDeviceConnection connection= mUsbManager.openDevice(device); 
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread
3.4 终止通信
当你完成数据的传输或者你的设备已拔出时,通过调用releaseInterface()和 close()来关闭接口和连接。

更多相关文章

  1. 【Android】Android之USB
  2. Android日志系统分析之日志设备驱动程序代码阅读
  3. Android(安卓)Power Manager分析
  4. android中adb命令大全
  5. android adb shell 命令大全
  6. Android(安卓)adb shell 命令大全
  7. Android(安卓)adb shell 命令大全
  8. Android图形系统的底层实现
  9. android底部栏中间按钮突出

随机推荐

  1. 工作总结|Android(安卓)自定义列表刷新控
  2. android 网络访问-图片处理优秀开源项目
  3. android九宫格实现
  4. Android横屏竖屏切换的问题
  5. Android学习入门
  6. 淘宝Android客户端技术分析
  7. android中Intent简介
  8. 程序设置横屏后,锁屏时会被销毁一遍,解锁时
  9. 自定义tabhost实现
  10. (翻译)又一个Android Sqlite库: Cupboard