USB Host(主机模式)

当 Android 设备处于 USB 主机模式时,它充当 USB 主机,为总线供电,并枚举连接的 USB 设备。Android 3.1 及更高版本支持 USB 主机模式。

API 概述

在开始之前,理解需要使用的类是很重要的。下表描述了 android.hardware.usb 包里的 USB 主机 API 函数。

Table 1. USB Host APIs

Class Description
UsbManager 负责枚举和与连接的 USB 设备通讯
UsbDevice 表示连接的 USB 设备并且包含访问其标识信息,接口和端点的方法
UsbInterface 表示 USB 设备的接口,它定义了设备的一组功能。 设备可以具有一个或多个接口进行通信。
UsbEndpoint 表示接口端点,它是该接口的通信通道。 接口可以有一个或多个端点,并且通常具有与设备进行双向通信的输入和输出端点。
UsbDeviceConnection 表示与设备的连接,该设备在端点上传输数据。 该类允许您以同步方式或异步方式来回发送数据。
UsbRequest 表示通过UsbDeviceConnection与设备通信的异步请求。
UsbConstants 定义与Linux内核的linux / usb / ch9.h中的定义对应的USB常量。

在大多数情况下,与 USB 设备通讯时需要使用所有这些类(UsbRequest 只在异步方式通讯的时候需要)。通常,会获取一个 UsbManager 来检索所需的 UsbDevice。当获取到设备时,需要查找合适的 UsbInterface 与接口中用于通讯的UsbEndpoint。一旦获取到正确的端点,打开一个 UsbDeviceConnection 与 USB 设备通讯。

Android Manifest 要求

下面的清单描述了在使用 USB host API 函数前需要添加到应用清单文件的内容:

1. 由于并非所有安卓设备被授权支持 USB host API 函数,因此需要包含一个 <uses-feature> 元素来声明你的应用使用 android.hardware.usb.host功能。

2. 设置应用的最低 SDK 版本为 API 级别 12 或更高。USB host API 函数在更早的 API 级别中不存在。

3. 如果你希望应用收到 USB 设备插入的通知,请在主活动中为 android.hardware.usb.action.USB_DEVICE_ATTACHED 意图指定<intent-filter> 和 <meta-data> 元素对。<meta-data> 元素指向一个外部 XML 资源文件,它声明了要检测的设备的信息。

4. 在 XML 资源文件中,为你想过滤的 USB 设备声明 <usb-device>元素。下表描述了 <usb-device> 的属性。

通常,如果要过滤特定的设备使用厂商和产品 ID,如果要过滤一组 USB 设备使用 USB 类、子类和协议,如大容量存储类和数码相机。

你可以指定这些属性中的一个或者全部,不指定属性匹配任何 USB 设备,因此在应用需要时才进行指定:

vendor-id

product-id

class

subclass

protocol (device or interface)

将资源文件保存在 res/xml/ 目录中。资源文件名(不含 .xml 扩展名)必须与您在 <meta-data> 元素中指定的文件名相同。XML 资源文件的格式在下面的示例中。

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>

在这种情况下,以下资源文件应该保存在 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 设备连接到 Android 设备时,Android 系统可以确定应用程序是否对连接的设备感兴趣。如果是这样,您可以根据需要建立与设备的通信。为此,您的应用程序必须:

1.通过使用 intent filter 在用户连接设备时收到通知或通过枚举已连接的 USB 设备来发现 USB 设备。

2. 请求用户连接 USB 设备的权限,如果尚未获得。

3. 通过在相应的接口端点上读写数据与 USB 设备进行通信。

发现设备

应用程序可以通过使用intent filter 在用户连接设备时收到通知或通过枚举已连接的 USB 设备来发现 USB 设备。如果您希望能够让应用程序自动检测到所需的设备,则使用 intent filter 非常有用。 如果要获取所有连接的设备列表,或者您的应用程序没有为 intent 进行过滤,则枚举已连接的 USB 设备的方法非常有用。

使用 intent filter(意图过滤器)

要使您的应用程序发现一个特定的 USB 设备,可以指定一个 intent filter 来过滤android.hardware.usb.action.USB_DEVICE_ATTACHED intent。 除了此 intent filter,您还需要指定一个资源文件,该资源文件指定USB设备的属性,如产品和供应商ID。 当用户连接与 device filter 匹配的设备时,系统会向他们显示一个对话框,询问他们是否要启动应用程序。 如果用户接受,应用程序自动获得访问设备权限,直到设备断开连接。

以下示例展示如何声明 intent filter:

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

在你的活动中,你可以像这样从 intent 中获取表示连接设备的 UsbDevice :

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

枚举设备

当应用程序运行时,如果应用程序有兴趣检查当前连接的所有 USB 设备,它可以枚举总线设备。使用 getDeviceList()方法获取所有已连接 USB 设备的哈希表,如果要从表中获取设备,通过作为键值传入的 USB 设备名。

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

如果需要,还可以从哈希表中获取 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设备进行通信之前,应用程序必须获得用户的许可。

Note:如果应用程序使用 intent filter 来发现连接时的 USB 设备,则如果用户允许您的应用程序处理 intent,则它将自动接收权限。如果没有,您必须在连接到设备之前在应用程序中明确请求权限。

在某些情况下,显式请求许可可能是必需的,例如当您的应用程序枚举已连接的USB设备,然后要与其进行通信时。在尝试与之通信之前,您必须检查访问设备的权限。如果没有,用户拒绝访问设备的权限时,您将收到 runtime 错误。

要明确获得许可,首先创建一个广播接收器。该接收器侦听当您调用 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);}}}}
};

要注册广播接收器,在活动的 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 的 intent,这是表示答案的布尔值。 在连接设备之前,请检查这个额外值是否为 true。

与设备通信

与USB设备的通信可以是同步或异步的。在任一情况下,您应该创建一个新线程来执行所有数据传输,才不会阻塞UI线程。要正确建立与设备的通信,您需要获得要进行通信的设备的相应的UsbInterface 和UsbEndpoint,并使用UsbDeviceConnection 在此端点上发送请求。一般来说,您的代码应该:

1. 检查UsbDevice 对象的属性,如产品 ID,供应商 ID或设备类,以确定是否要与设备进行通信;

2. 当您确定要与设备通信时,请找到与合适的UsbEndpoint 进行通信的相应UsbInterface。接口可以具有一个或多个端点,并且通常会具有用于双向通信的输入和输出端点;

3. 找到正确的端点时,在该端点上打开一个UsbDeviceConnection;

4. 使用bulkTransfer() 或controlTransfer() 方法提供在端点上传输的数据。您应该在另一个线程中执行此步骤,以防止阻塞主 UI 线程。有关在 Android 中使用线程的更多信息,请参阅 Processes and Threads。

以下代码片段是进行同步数据传输的简单方法。您的代码应该有更多的逻辑来正确找到正确的接口和端点进行通信,并且还应该在与主UI线程不同的线程中进行数据传输:

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

要异步发送数据,使用 UsbRequest类来 initialize 和 queue 一个异步请求,然后调用 requestWait() 等待结果。

终止与设备通信

当你与设备通信完成或者设备拔出时,调用 releaseInterface() 与 close() 方法关闭 UsbInterface 与 UsbDeviceConnection。为了监听拔除事件,如下所示创建广播接收器:

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 中创建广播接收器允许应用在运行时只处理拔除事件。通过这种方式,广播事件只会发送到当前正在运行的应用程序而不是广播到所有应用。

原文链接:https://developer.android.com/guide/topics/connectivity/usb/host.html

安卓USB开发教程 二 USB Host相关推荐

  1. 安卓USB开发教程 一 USB Host 与 Accessory

    安卓通过两种模式:USB Accessory 与 USB Host 模式支持多种 USB 外设与安卓 USB 配件(实现安卓配件协议的硬件).在 USB 配件模式下,外部 USB 硬件充当 USB 主 ...

  2. 安卓USB开发教程 三 USB Accessory

    USB Accessory(配件模式) USB 配件模式允许用户连接专为 Android 设备设计的 USB 主机硬件.配件必须遵守 Android Accessory Development Kit ...

  3. Libusb开发教程三 USB设备程序开发

    首先,需要指出本篇博客的基础仍然是基于 libusb V1.0 以下.主要考虑到保持与之前博客的连贯性,在上一篇博客中介绍了老版本中可以被调用的 API 以及功能介绍,对于库中 API 接口函数的使用 ...

  4. 嵌入式USB开发系列(1):USB简介

    嵌入式USB开发系列(1):USB简介 文章目录 嵌入式USB开发系列(1):USB简介 1. USB的优势 2. USB协议标准 3. USB通信接口 声明 声明:USB资料网站 链接,相关协议和文 ...

  5. MIP开发教程(二) 使用MIP-CLI工具调试MIP网页

    初始化 MIP 配置 新建一个 MIP 网页 编写 MIP 网页代码 校验 MIP 网页 调试 MIP 网页 1. 初始化 MIP 配置 首先在html目录下进行初始化 MIP 配置: $ mip i ...

  6. 《USB开发大全》—USB软硬件开发指南,无可替代的工具书

    <USB开发大全>-USB软硬件开发指南,无可替代的工具书 内容简介 <USB开发大全(第4版)>介绍了有关通用串行总线(Universal Serial Bus,USB)的工 ...

  7. 安卓USB开发教程 四 安卓 AOA

    Android 开放性配件协议(AOA) Android 开放性配件协议(AOA)支持允许外部 USB 硬件(Android USB 配件)与工作在配件模式下的 Android 设备进行交互.当处于配 ...

  8. RockChip Linux USB 开发(二)

    目录 一:Linux USB 驱动框架 二:USB PHY驱动开发 1.USB 2.0 PHY驱动开发 </

  9. linux usb 子系统(二)- host driver

    了解usb host driver. 1.USB Subsystem Framework   The following chart shows the framework of the USB su ...

最新文章

  1. 【每日DP】day 5、P1095 守望者的逃离(好像悟到了DP的真谛)难度⭐⭐★
  2. 利用日志传送实现高可用性
  3. Spring WebSocket初探2 (Spring WebSocket入门教程)
  4. S3C2440时钟体系
  5. linux cache buffer区别,Linux buffer/cache异同
  6. python英文词频统计代码_python实现中文和英文的词频统计功能方法汇总
  7. putty和WinSCP后门检查及清理方式
  8. 微信android 流畅,【黑科技】微信只需这样操作,立刻提升流畅度和使用效率
  9. Swift3.0 功能二 (表情键盘与图文混排)
  10. android制作弹出框样式,Android Dialog 弹出框 自定义 样式
  11. Android 简单实现控件的拖动
  12. mysql 给root授权_mysql授权
  13. 商业模式画布 - 天涯的日志 - 网易博客
  14. 10大程序员必逛网站,良心推荐,建议收藏!
  15. 计算机如何提高开机速度?
  16. 【喜讯】PerfMa再获高瓴创投领投1.5亿A++轮融资
  17. C 语言实现面向对象编程
  18. ros ubuntu 卸载_ROS的安装、卸载
  19. 【内网穿透服务器】使用Frp外网访问内网FTP服务器(以访问内网samba服务为例)
  20. STS报错“HttpServlet cannot be resolved to a type”

热门文章

  1. spring—配置数据源
  2. 如何使用Elasticsearch,Logstash和Kibana实时可视化Python中的日志
  3. htt://3g.hn_根据我对“询问HN:谁在招聘?”的分析,开发人员技能发展趋势
  4. ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
  5. jquery元素节点操作
  6. 微信(支付宝)小程序蓝牙4.0线上项目
  7. https 与 http
  8. 18、Java并发性和多线程-饥饿与公平
  9. sql语句按月份统计查询
  10. 弹出框 每次打开 滚动条置顶_微信置顶文字怎么弄?微信置顶一句话教程