Android USB Host(Android USB 主机通讯)

翻译很烂,纯当练手,大家权当消遣好了…   :》
当你的Android手机是在USB主机模式下,它充当USB主机,开启设备,并列举已连接的USB设备。 这种模式,在Android 3.1及以上版本的支持。

API 预览

在开始学习USB Host之前,理解并掌握你所需要用到的类是很重要的。下面的表格描述了 android.hardware.usb包下的USB host 的API。
Class Description
UsbManager 可以让你列举USB设备,并和设备交互;
UsbDevice
表示已连接的USB设备, 包含了访问设备标识信息的方法、接口和挂在点。
UsbInterface
表示设备接口,定义了一些列的功能函数。一个设备可以包含一个或者多个接口。
UsbEndpoint
表示一个挂载点接口,定义了一个交互通道。一个接口可以包含一个或者多个挂载点,
通常都包含用于和USB设备交互的输入输出双向端点 。
UsbDeviceConnection
表示到USB设备的一个基于端点通信的接口,这个类支持同步或者异步数据的来回通讯;
UsbRequest 代表一个异步的,基于UsbDeviceConnection通讯的异步请求。
UsbConstants 定义了一些USB常量,与linux内核中的 linux/usb/ch9.h 中的定义一致。
在和USB设备交互的时候,通常情况下,你需要用到所有的这些类(除了交互的时候,只需要用到 UsbRequest)。总的来说,你首先需要获取   UsbManager对象来查询目标设备 UsbDevice。当获得设备 UsbDevice之后,你需要找到适当的   UsbInterface以及该接口对应的 UsbEndpoint  ,从而进行交互。一旦拿到真确的端点,打开连接 UsbDeviceConnection,以此和USB设备进行交互。

Manifest文件的必要节点

下面的列表,列出了在使用USB host的API之前,你所需要添加到Manifest文件中的东西:
  • 由于不能确保所有的Android设备都支持USB host 的API , 我们可以在Manifest文件中加入 <uses-feature>节点,来声明我们的应用需要android.hardware.usb.host 支持.
  • 设置应用程序的最低支持的SDK版本为12或者更高. USB 主机模式的 API 在12以前的版本上不适用.
  • 如果希望你的应用能够接收到USB设备挂在的通知,则需要在你的主Activity的android.hardware.usb.action.USB_DEVICE_ATTACHED过滤器中指定 <intent-filter> 和<meta-data> 节点对.  <meta-data> 节点对应着一个外部XML 资源文件,这个资源文件定义了你想检测的设备的一些唯一标识信息.

在XML资源文件中,通过声明节点 <usb-device> 来过滤你想要过滤的设备. 以下列表列出了 <usb-device>的属性. 总的来说, 使用 vendor-id 和 product-id 来过滤指定的USB设备,使用 class, subclass 和 protocol 来过滤一组设备, 比如说大容量存储设备和数码相机. 你可以指定所有的属性或者一个都不指定.如果你什么属性都不设置,就将匹配所有的USB设备,当程序需要的时候,你可以这么指定:

  • vendor-id
  • product-id
  • class
  • subclass
  • protocol (device or interface)

该资源文件保存在 res/xml/ 目录下. 它的文件名(不包含.xml后缀名) 必须和<meta-data> 节点指定的名字一样. 文件的格式样式如下example:

Manifest文件 和资源文件

下面是一个简单的manifest文件及其对应的资源文件:
<manifest ...><uses-feature android:name="android.hardware.usb.host" /> <uses-sdk android:minSdkVersion="12" />...<application><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></application>
</manifest>
在上面的manifest文件下,对应的资源文件必须保存为 res/xml/device_filter.xml,并且使用特定的属性来过滤任何USB设备:
<?xml version="1.0" encoding="utf-8"?>
<resources><usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>

使用USB设备

当用户将一个USB设备连接到Android设备, Android系统可以决定你的程序是否有兴趣连接这个USB设备. 若确实有, 你的程序可以和设备如愿的进行交互. 为了让系统知道我们的应用程序确实有兴趣, 你必须做到:

  1. 你可以通过意图过滤器(Intent Filter)使得当用户插入USB设备时,程序能够接受到USB设备挂载通知,或者列举出已经连接的USB设备,这样,程序就能够找到那些已连接的USB设备.
  2. 若程序还没有获得连接USB设备的权限,跟用户请求.
  3. 使用适当的接口端点进行USB数据的读写.

寻找USB设备

你的应用可以使用意图过滤器(Intent Filter)使得程序可以接收到用户USB挂载通知或者列举出那些已连接的USB设备. 如果你希望你的应用能够自动的探寻的目标设备,使用一个意图过滤器是很有用的. 如果你希望获得一个所有的已连接的设备的列表或者你的应用并没有使用意图来过滤,那么列举出所有已连接的USB设备这个方式很有用.

使用意图过滤器(Intent Filter)

为了使得你的应用能够发现某个USB设备, 你可以指定一个android.hardware.usb.action.USB_DEVICE_ATTACHED 意图来过滤设备. 指定了这个意图之后, 你需要为它指定一个包含了某个USB设备的特定属性(比如说 product-id 和 vendor-id)的资源文件. 当用户插入一个与意图过滤器符合的设备时, 系统将弹出一个包含了这些信息的对话框,来询问用户是否能够启动你的应用 ,  如果用户接受了请求,你的应用将自动有权限去访问这个USB设备,直到USB设备断开连接.

下面的例子表明了如何声明意图过滤器:

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

下面的例子表明了如何声明对应的指定了你所感兴趣的USB设备的资源文件:

<?xml version="1.0" encoding="utf-8"?>
<resources><usb-device vendor-id="1234" product-id="5678" />
</resources>

在你的Activity 中, 你可以像下面这样获取 UsbDevice 对象,该对象代表了从意图(Intent)中检测到的设备:

UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); 

列举USB设备

如果你的应用在运行时,想要获得所有的当前已经连接的USB设备, 可以枚举出所有挂在在IO上的设备. 使用方法 getDeviceList() 获取一个包含所有已挂载的USB设备的HashMap. 这个HashMap使用USB设备的名字作为键值,如果你想从这个HashMap获取设备.

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
UsbDevice device = deviceList.get("deviceName");

如果你想, 你同样也可以从这个HashMap种获取一个迭代器(iterator)来一个接一个的处理每一个设备对象 :

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){UsbDevice device = deviceIterator.next()//your code
}
 

获取与设备交互的权限

在和USB设备交互的时候,应用程序必须从用户那获得交互的权限。

注意: 当USB设备连接的时候,如果你的应用使用意图过滤器来发现设备, 并且在应用安装的时候,用户允许你的应用处理这些事件,则应用将自动获得权限,否则, 在连接设备之前,你的应用必须明确的跟用户请求权限.

在一些情况下,明确的请求权限是必须的,比如当你的应用试图枚举已连接的USB设备并期望和其中一个交互的时候. 在应用于设备交互之前,你必须检查应用是否具有访问设备的权限. 否则的话,如果用户拒绝给予应用访问设备的权限,你将收到一个运行时错误.

为了明确获得权限,首先创建一个广播接收者(Broadcast Receiver). 当你调用方法requestPermission()的时候, 这个接收者能够得到广播, 从而监听到你的意图. 调用方法 requestPermission() 将为用户弹出对话框,以询问是否允许应用连接设备. 以下的简单的例子表明了如何创建这个广播接收者:

private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
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){//call method to set up device communication}}else{Log.d(TAG, "permission denied for device " + device);}}}}
};

为了注册这个广播接收者,你需要在Activity的 onCreate() 中添加如下代码:

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():

UsbDevice device;
...
mUsbManager.requestPermission(device, mPermissionIntent);

当用户回应对话框,你的广播接收者将接收到包含EXTRA_PERMISSION_GRANTED 的额外数据的意图, 这些额外的数据是一个代表着用户的回应的boolean值. 只有检测到这个额外的数据为true, 才有权限连接设备.

与设备交互

与设备交互,可以是同步的,也可以是异步的. 不管哪种情况, 你都需要创建一个新的线程,用于所有的数据传输,以致不阻塞UI主线程. 为了正确的建立与设备的交互, 你需要获得对应的UsbInterface 和 设备的 UsbEndpoint ,这个UsbEndpoint是你使用UsbDeviceConnection进行交互和发送请求的基本. 总的来说, 你的代码应该像这样:

  • 检测遍历 UsbDevice 对象的属性, 比如 product-id, vendor-id, 或者是决定你是否想要和设备交互的设备类class节点.
  • 当你确定你的应用需要和设备进行交互的时候, 找出合适的UsbInterface 以及用于和这个接口交互的合适的UsbEndpoint . 接口可以含有一个或者多个端点, 而通常情况下,都含有一个输入输入和输出的交互端点对.
  • 当找到正确的端点的时候,在这个端点上打开连接UsbDeviceConnection .
  • 在这个端点上,使用方法bulkTransfer() 或者controlTransfer() 来提供传输的数据. 你应该在另一个线程中实现这一步,从而避免阻塞UI主线程. 关于如何在Android中使用线程,请查看Processes and Threads.

下面的一小段代码,是一种简单的同步的数据传输方式. 在实际中,你的代码应该包含更多的逻辑来正确的获取到正确的交互接口和端点,而且应该在不同的线程中做数据的传输操作,而不是在UI主线程中:

private Byte[] bytesprivate 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




为了异步的发送数据, 我们使用类UsbRequest 来初始化initialize 和序列化 queue 一个异步的请求, 然后调用方法requestWait()等待请求.

更多信息请看AdbTest sample, 例中展示了如何进行大容量的异步传输, 还有例子MissleLauncher sample, 这个例子展示了如何异步的监听一个可阻断的端点。

中断与USB设备的交互

当完成了与设备的交互、设备断开、关闭接口UsbInterface或者连接UsbDeviceConnection调用了方法releaseInterface()close(). 为了监听设备断开事件,我们创建一个像下面这样创建一个广播接收者:

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 closes communication with the device}}}
};
 
在应用中创建,而不是在manifest文件中创建广播接收者,可以使你的应用只在应用运行的时候才处理连接断开事件. 这种方法,断开事件只被发送到当前运行的应用,而不是发送给所有的应用. 

Android USB 主机模式相关推荐

  1. android usb attached,Android USB主机模式服务 – 基于USB_DEVICE_ATTACHED启动

    我想在Android中编写一个基于USB_DEVICE_ATTACHED意图启动的服务.因此,基本上我的服务应该在连接特定USB设备(FT232C – VID:PID 0403:6010)时启动,并在 ...

  2. Android的联通性---USB主机模式(三)

    获取跟设备通信的权限 在跟USB设备进行通信之前,你的应用程序必须要获取用户的许可. 注意:如果你的应用程序使用Intent过滤器来发现接入的USB设备,而且用户允许你的应用程序处理该Intent,那 ...

  3. 【连载】【FPGA黑金开发板】NIOSII那些事儿--USB主机模式(二十一)

    声明:本文为原创作品,版权归本博文作者所有,如需转载,请注明出处http://www.cnblogs.com/kingst/ 上一节,我们讲了USB的设备模式,可以实现计算机与黑金开发板的数据通信.这 ...

  4. android usb存储模式,Android USB连接说明:MTP,PTP和USB大容量存储器

    为什么现代Android设备不支持USB海量存储 USB大容量存储(也称为" USB大容量存储设备类",USB MSC或UMS )是旧版Android将它存储暴露给计算机的方式,当 ...

  5. android usb 开发:如何跳过usb权限询问,解决绕过android下apk使用usb设备权限查询相应问题,自动获取usb权限...

    很多android的应用在使用usb设备时,尤其是usb摄像头,前段时间编写了一个有关usb设备的apk,但是在使用时总是会跳出系统对话框,用户体验很差,如下图所示,所以一直想要解决这个问题,在网上说 ...

  6. Android 连接USB设备(主机模式)

    Android 连接USB设备(主机模式) Android 连接USB设备(配件模式) 两种模式(主机.配件) 首先,要了解Android 连接USB设备主要通过两种模式, USB 配件模式. USB ...

  7. Android USB的AOA协议设备端(主机模式,配件模式),ADB连接

    USB的ADB/AOA协议(一种是ADB模式,一种是AOA模式).AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议. ADK中与USB配件模式相关的两个类是U ...

  8. 安卓之USB主机(Host)与配件(Accessory)模式

    安卓设备与USB硬件通讯时有两种模式可以选择:USB Host 模式与 USB Accessory 模式.从 USB 逻辑角色来说,USB Host 模式是指安卓设备作为 USB 主机,所有活动均由安 ...

  9. 基于AOA协议的android USB通信

    摘 要:AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议.该协议拓展了Android设备USB接口的功能,为基于Android系统的智能设备应用于数据采集和设 ...

最新文章

  1. matlab plot3d_号称轻量级MATLAB的数学工具—Maple 2019.2
  2. OFBiz + Opentaps 目录管理 四. 产品(二)可配置产品
  3. python图像分割动态域值_python+opencv阈值分割
  4. fir.im Weekly - 做一款 App 需要考虑什么
  5. Python 基础详解-列表的反转与排序!跬步千里
  6. VTK:PolyData之ColoredPoints
  7. vue-router 动态路由匹配
  8. 海康威视、大华监控摄像头rtsp地址规则
  9. USB接口类型的区别
  10. 2021-09-02重排链表
  11. Ubuntu 12.04 LTS 键盘快捷键(转)
  12. 九章云极DataCanvas公司荣获机器之心三大奖项,助力产业数智化升级
  13. scrapy 官方文档(入门必备)
  14. 还在为word排版而发愁?word的实验报告模板word数学建模模板免费领~(开头直接放百度网盘链接,直接拿去用就行)
  15. python 获取图像亮度和锐度,pytesseract 获取图片上字符串,及增加亮度,色感,对比度,锐度...
  16. 非本小伙花了两年从小公司到蚂蚁金服,面试经验分享
  17. 面试|复习小册(2022-9)
  18. 【课设分享】基于51单片机的恒温控制器系统
  19. 搭建ARM DS-5 STREAMLINE
  20. python实现采样函数_PR Sampling Ⅰ: 蒙特卡洛采样、重要性采样及python实现

热门文章

  1. Mac 破解IDEA 持续更新
  2. iOS上应用如何兼容32位系统和64位系统
  3. LoRaWAN协议-物理层(PHY)详解
  4. 两个可能常用到的几何知识(圆与椭圆的方程、求垂直向量)
  5. 深度挖掘新闻营销带给企业的好处和优势
  6. centos下ftp安装及添加账户
  7. chrome插件安装
  8. 杰理之优化电脑长时间播放没声音【篇】
  9. 浅析Android中build.gradle的实用技巧
  10. ARM6818开发板画任意矩形,圆形,三角形,五角星,6818开发板画太极,画五星红旗(含码源与思路)