USB Accessory(配件模式)

USB 配件模式允许用户连接专为 Android 设备设计的 USB 主机硬件。配件必须遵守 Android Accessory Development Kit 文档中列出的 Android 配件协议。 这使得 Android 设备无法充当 USB 主机时仍然可以与 USB 硬件交互。 当 Android 设备处于 USB 配件模式时,所连接的 Android USB 配件充当主机,为 USB 总线供电,并枚举所连接的设备。 Android 3.1(API 级别12)支持 USB 配件模式,该功能也被以附加组件库的方式回溯到 Android 2.3.4(API 级别10),以支持更广泛的设备。前提是厂商必须在系统镜像中添加附加组件库。

选择正确的 USB Accessory API 函数

尽管 USB accessory API 函数在 Android 3.1 引入到平台,通过使用 Google APIs 附加库的方式用在 Android 2.3.4 上。由于这些 APIs 使用外部库的方式回溯,有两个包可以导入来支持 USB 配件模式。根据你要支持的安卓设备,您可能要使用一个库而不是另一个:

com.android.future.usb: 为了在 Android 2.3.4 中支持 USB accessory 模式,Google APIs add-on library 包括回溯的 USB accessory  API,它们包含在此命名空间中。 Android 3.1 还支持在此命名空间中导入和调用类,以支持使用附加库编写的应用程序。 这个附加库是围绕 android.hardware.usb accessory API 的简版 wrapper,不支持USB主机模式。 如果您想支持最广泛的支持 USB accessory 模式的设备,请使用附加库并导入此软件包。 重要的是要注意,并非所有的 Android 2.3.4 设备都需要支持 USB 配件功能。 每个单独的设备制造商决定是否支持此功能,这就是为什么必须在 manifest 文件中声明它。
android.hardware.usb: 此命名空间包含在 Android 3.1 中支持 USB accessory 模式的类。 该软件包作为 framework API 的一部分,Android 3.1 支持 USB accessory 模式,而不需要附加库。 如果您只关心具有 USB accessory 模式硬件支持的 Android 3.1 或更新版本,您可以在清单文件中声明使用此软件包。

安装 Google APIs 附加库

API 概述

由于附加库是 framework API 的 wrapper,因此支持 USB accessory 功能的类很相似。 即使您正在使用附加库,也可以使用 android.hardware.usb 的参考文档。

Note:但是,您应该注意的附加库和 framework API 之间存在较小的用法差异。
下表描述支持 USB accessory API 的类:

Class Description
UsbManager 允许枚举以及与已连接 USB 配件通讯
UsbAccessory 表示USB 配件,包含访问其标识信息的方法

附加库和平台 APIs 的使用差别

在使用 Google APIs 和平台 APIs 之间有两处使用区别。
如果正在使用附加库,必须以下列方式获取 UsbManager:

UsbManager manager = UsbManager.getInstance(this);

如果没在使用附加库,必须以下列方式获取 UsbManager:

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

当您使用 intent filter 过滤连接的配件时,UsbAccessory 对象包含在传递给应用程序的 intent 内。 如果正在使用附加库,则必须以下列方式获取 UsbAccessory 对象:

UsbAccessory accessory = UsbManager.getAccessory(intent);

如果没在使用附加库,必须以下列方式获取 UsbAccessory:

UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

安卓 Manifest 要求

以下列表描述了在使用 USB accessory API 之前需要添加到应用程序的 manifest 文件中的内容。manifest and resource file examples 展示了如何声明这些项目:

1. 因为并非所有 Android 设备被授权支持 USB accessory API,因此包含一个 <uses-feature> 元素,声明您的应用程序使用 android.hardware.usb.accessory 功能。

2. 如果您正在使用附加库,请添加指定 com.android.future.usb.accessory 的 <uses-library> 元素。

3. 如果您正在使用附加库,请将应用程序的最小 SDK 设置为 API Level 10,如果使用的是android.hardware.usb 包,则将其设置为12。

4. 如果您希望应用程序在 USB 配件连接时收到通知,请在主要活动中为 android.hardware.usb.action.USB_ACCESSORY_ATTACHED 意图指定 <intent-filter> 和 <meta-data> 元素对。<meta-data> 元素指向一个外部XML资源文件,它声明了您想检测的配件的标识信息。

在XML资源文件中,为要过滤的配件声明 <usb-accessory> 元素。每个 <usb-accessory> 可以具有以下属性:

  • manufacturer
  • model
  • version

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

Manifest 和 资源文件示例

以下示例展示了一个 manifest 样例及相应的资源文件:

<manifest ...><uses-feature android:name="android.hardware.usb.accessory" /><uses-sdk android:minSdkVersion="<version>" />...<application><uses-library android:name="com.android.future.usb.accessory" /><activity ...>...<intent-filter><action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /></intent-filter><meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"android:resource="@xml/accessory_filter" /></activity></application>
</manifest>

在这个案例中,下面的资源文件应该保存在 res/xml/accessory_filter.xml 中,并且指定具有相关 model、manufacturer、version 的配件应该被过滤。配件将这些属性发送给 Android 设备:

<?xml version="1.0" encoding="utf-8"?><resources><usb-accessory model="DemoKit" manufacturer="Google" version="1.0"/>
</resources>

使用配件

当用户将 USB 配件连接到 Android 设备时,Android 系统可以决定您的应用程序是否对连接的配件感兴趣。 如果是这样,如果需要,您可以设置与附件的通信。如果是这样,您可以根据需要建立与设备的通信。为此,您的应用程序必须:

1. 通过使用 intent filter 过滤配件连接事件来发现配件或通过枚举已连接的配件找到正确的配件。

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

3. 在正确的接口端点上读写数据与 USB 配件进行通信。

发现配件

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

使用 intent filter(意图过滤器)

要使您的应用程序发现一个特定的 USB peijia,可以指定一个 intent filter 来过滤 android.hardware.usb.action.USB_ACCESSORY_ATTACHED intent。 除了此 intent filter,您还需要指定一个资源文件,该资源文件指定 USB 配件的属性,如 manufacturer、model 和 version。 当用户连接与 accessory filter 匹配的配件时,

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

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

以下示例展示如何声明相应资源文件,其指定了感兴趣的 USB 配件:

<?xml version="1.0" encoding="utf-8"?><resources><usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" />
</resources>

在你的活动中,你可以像这样从 intent 中获取表示连接附件的 UsbAccessory(使用附加库):

UsbAccessory accessory = UsbManager.getAccessory(intent);

或者像这样(使用平台 APIs):

UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

枚举配件

当应用程序运行时,可以让应用程序枚举已经标识自己的配件。

使用 getAccessoryList() 方法获取所有已连接 USB 配件的数组:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbAccessory[] accessoryList = manager.getAcccessoryList();

Note:同一时间只可以支持一个已连接配件。

获取与配件进行通信的权限

在与 USB 配件进行通信之前,应用程序必须获得用户的许可。

Note:如果应用程序 uses an 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) {UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {if(accessory != null){//call method to set up accessory communication}}else {Log.d(TAG, "permission denied for accessory " + accessory);}}}}
};

要注册广播接收器,在活动的 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() 方法:

UsbAccessory accessory;
...
mUsbManager.requestPermission(accessory, mPermissionIntent);

当用户响应对话框时,广播接收器收到包含额外值 EXTRA_PERMISSION_GRANTED 的 intent,这是表示答案的布尔值。 在连接配件之前,请检查这个额外值是否为 true。

与配件通信

您可以使用 UsbManager 与配件通信,以获取文件描述符,您可以配置输入和输出流来读取和写入数据到描述符。 数据流表示配件的输入和输出批量端点。 您应该在另一个线程中建立设备和配件之间的通信,因而不会阻塞主UI线程。 以下示例展示如何打开配件进行通信:

UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;...private void openAccessory() {Log.d(TAG, "openAccessory: " + accessory);mFileDescriptor = mUsbManager.openAccessory(mAccessory);if (mFileDescriptor != null) {FileDescriptor fd = mFileDescriptor.getFileDescriptor();mInputStream = new FileInputStream(fd);mOutputStream = new FileOutputStream(fd);Thread thread = new Thread(null, this, "AccessoryThread");thread.start();}
}

在线程的 run() 方法中,可以使用 FileInputStream 或 FileOutputStream 对象来读写配件。 使用 FileOutputStream 对象从配件读取数据时,请确保使用的缓冲区足够大以存储 USB 数据包数据。 Android 配件协议支持高达16384字节的数据包缓冲区,因此为了简单起见,您可以选择始终声明缓冲区为此大小。

Note:注意:在较低级别,USB 全速配件的数据包为64字节,USB 高速配件为512字节。 为了简单起见,Android 配件协议将两个速度的数据包捆绑在一起成为一个逻辑数据包。

有关在 Android 中使用线程的更多信息,请参阅 Processes and Threads。

终止与配件通信

当你与配件通信完成或者配件拔出时,调用 close() 方法关闭你打开的描述符为了监听拔除事件,如下所示创建广播接收器:

BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);if (accessory != null) {// call your method that cleans up and closes communication with the accessory}}}
};

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

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

安卓USB开发教程 三 USB Accessory相关推荐

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

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

  2. 安卓USB开发教程 二 USB Host

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

  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. 《USB开发大全》—USB软硬件开发指南,无可替代的工具书

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

  6. MIP开发教程(三) 使用MIP-CLI工具调试组件

    一 . 在 mip-extensions 仓库中创建新的组件 二 . 预览调试组件 三 . 在 MIP 页中引用自己编写的 MIP 组件 四 . 组件提交到 GitHub 仓库时需要进行校验 站长开发 ...

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

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

  8. 安卓USB开发教程 六 安卓 AOA 2.0

    Android Open Accessory Protocol 2.0 目录 Detecting AOAv2 support Audio support HID support Interoperab ...

  9. USB开发基础:USB设备的开发流程

    USB设备的开发一般包括主机端(上位机)驱动程序的开发(如果您的USB设备符合某一标准设备类且主机端已经提供了此类设备的驱动程序的话,则可以省掉此步骤)和USB设备端驱动程序的开发,有时还可能包括主机 ...

最新文章

  1. 利用Attribute和IErrorHandler处理WCF全局异常
  2. Racktables(一)的资产管理软件安装配置
  3. 飞向天国:儿童智力单机游戏6岁-8岁
  4. jquery.ajax
  5. 爬虫实战:过年你被催婚啦吗?爬取相亲网站,看看当下年轻小姐姐的择偶观。
  6. mongodb--find高级用法
  7. 缓存-分布式锁-分布式锁原理与使用
  8. python2clock_控制fps的时钟Clock类源码
  9. Taro+react开发(47)taro中消息机制
  10. wpf将文字转化为图形_将创新转化为实际应用
  11. 苦逼or高薪程序猿,你选谁?WEB前端这个行业普遍年薪20万+,吃鸡如开挂!
  12. iOS 柱状图的定制
  13. mac 输入法/键盘 锁定
  14. Code Server 是什么?
  15. 微型计算机硬件系统包括什么,微型计算机的硬件系统包括什么?
  16. 【沃顿商学院学习笔记】商业基础——Financing:05 名义利率和实际利率 APR EAR
  17. 免费在线客服 livezilla 中文版,安装+使用教程
  18. 2022广东最新初级消防员模拟考试试题及答案
  19. c++二分法求平方根
  20. Golang内存分析工具gctrace和pprof实战

热门文章

  1. sql优化技巧_使用这些查询优化技巧成为SQL向导
  2. 成为一名真正的数据科学家有多困难
  3. 蠕变断裂 ansys_如何避免范围蠕变,以及其他软件设计课程的辛苦学习方法
  4. 如何对第一个Vue.js组件进行单元测试
  5. arduino服务器_如何使用Arduino检查Web服务器的响应状态
  6. ios 跨域_如何在iOS和Android中建立跨域通信桥
  7. 七日掌握设计配色基础_掌握正确的基础知识:如何设计网站的导航,搜索和首页...
  8. bootstrap table入门例子
  9. CDU集训代码:基础算法和数据结构2
  10. ckeditor 框架分析 几个核心“人物”