安卓USB开发教程 三 USB Accessory

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 附加库

如果要安装该附加库,可以通过使用 SDK Manager 安装 Google API Android API 10 软件包。有关安装附加库的更多信息,请参阅 Installing the Google APIs Add-on

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









本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403061.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android ADB

Android 调试桥 本文内容 adb 的工作方式在您的设备上启用 adb 调试通过 WLAN 连接到设备查询设备将命令发送至特定设备安装应用设置端口转发将文件复制到设备/从设备复制文件停止 adb 服务器adb 命令参考发出 shell 命令 调用 Activity Manager (am)调用软件包管理器 (pm)进行…

轻松访问 Android 系统源码与下载

有时研究 Android 某个特性或者协议的时候需要参阅安卓系统源代码中代码实现或者协议文档等。通过正常的建立 repo&#xff0c;git 获取十分耗时&#xff0c;并且速度很慢&#xff0c;除非是需要重新编译系统&#xff0c;定制系统才需要这样做。因此&#xff0c;推荐一个 Andro…

安卓系统源代码下载(官方教程)

下载源代码 Android 源代码树位于由 Google 托管的 Git 代码库中。Git 代码库中包含 Android 源代码的元数据&#xff0c;其中包括与对源代码进行的更改以及更改日期相关的元数据。本文档介绍了如何下载特定 Android 代码流水线的源代码树。 要从特定设备的出厂映像开始&#x…

Cygwin 下载极速源推荐

Cygwin 默认列表中的源下载速度太慢&#xff0c;国内使用时常用以下几个源&#xff0c;经过实际使用速度很快&#xff0c;下载时不妨几者都尝试下&#xff1a; 如上图所示&#xff0c;下载时在此栏填写 URL 地址即可&#xff0c;推荐地址&#xff1a; http://mirrors.sohu.com…

安卓USB开发教程 四 安卓 AOA

Android 开放性配件协议&#xff08;AOA&#xff09; Android 开放性配件协议&#xff08;AOA&#xff09;支持允许外部 USB 硬件&#xff08;Android USB 配件&#xff09;与工作在配件模式下的 Android 设备进行交互。当处于配件模式的 Android 设备被供电&#xff0c;所连接…

安卓USB开发教程 五 安卓 AOA 1.0

Android Open Accessory Protocol 1.0&#xff08;AOA 协议 1.0&#xff09; Android USB 配件必须遵从 Android Open Accessory&#xff08;AOA&#xff09;协议&#xff0c;该协议定义了配件如何检测和建立与 Android 设备的通信。配件应执行以下步骤&#xff1a; 1. 等待并…

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

Android Open Accessory Protocol 2.0 目录 Detecting AOAv2 support Audio support HID support Interoperability with AOAv1 Connecting AOAv2 without an Android app This document describes changes in the Android Open Accessory (AOA) protocol since its initial re…

Linux 驱动编译报错:error: macro __DATE__ might prevent reproducible builds [-Werror=date-time]

编译驱动时遇到这个错误提示&#xff0c;表示当前编译环境中将关于 DATE 以及 TIME 的警告也作为错误来进行处理的。有如下几种方法可以参考&#xff1a; 1. 在编译驱动的相应 Makefile 中增加一行&#xff1a;CFLAGS -Wno-errordate-time&#xff0c;然后保存重新 make&…

Java 结构体之 JavaStruct 使用教程一 初识 JavaStruct

Javastruct 是什么 简而言之&#xff0c;Javastruct 是一个第三方库&#xff0c;用于像处理 C 或者 C 结构体那样处理 java 对象。也即利用 Javastruct 可以在 java 上实现类似于结构体的功能和操作。 Javastruct 的用途 在 java 或者 Android 应用程序与一些嵌入式设备通讯…

Java 结构体之 JavaStruct 使用教程二 JavaStruct 用例分析

使用环境 前一篇在介绍 JavaStruct 类时指定了使用库使用环境为 Java 5 及以上&#xff0c;也即开发我们使用的 JDK 版本为1.5及以上就可以了。以下讲解的用例可以直接将 code 直接粘贴到 java 的 main 函数中执行就可以了&#xff0c;后面会给出测试用例和结果。 使用方法 Jav…

Java 结构体之 JavaStruct 使用教程三 JavaStruct 数组进阶

经过前面两篇博客的介绍&#xff0c;相信对于 JavaStruct 的认识以及编程使用&#xff0c;读者已经有一定的基础了。只要理解和实践结合起来&#xff0c;掌握还是很容易的。下面进行一些数组使用方面的实例说明及演示。 在结构体类中使用数组有几种方式&#xff0c;可以使用静…

Android开发如何使用JNA

1. JNA&#xff08;Java Native Access&#xff09;项目已经迁移到 github&#xff0c;最新的项目链接&#xff1a;https://github.com/java-native-access/jna 。首先前往该地址下载使用 JNA 需要的两个 jar 库文件&#xff0c;jna.jar&#xff0c;jna-platform.jar 。 2. 在…

JAVA循环队列

关于自定义循环队列的实现原理和要点可以参见之前的博文系列&#xff1a;循环队列及C语言实现。这里主要对JAVA下的具体实现方式与原理进行说明。 一、JAVA 中已经自带了 Queue、DQueue、ArrayList、LinkedList 等常用的数据结构&#xff0c;为什么还要单独实现循环队列&#…

VMware 虚拟机占用磁盘空间

使用VMware创建的虚拟机尽管已经设定分配的磁盘大小&#xff0c;但仍然会发现虚拟机占用的磁盘空间会越来越大&#xff0c;而直观体现就是虚拟机系统文件 vmdk 不断增大。因此下面介绍一个简单的方法&#xff0c;使用 VMware 自带的工具对 vmdk 文件进行压缩以节省磁盘空间。拿…

frameworks/av/media/CedarX-Projects/CedarAndroidLib/LIB_KK44_/Android.mk: No such file or directory

在安卓系统编译过程中如果遇到上述或者与之类似的错误&#xff0c;可以采取相同的处理方法进行解决。直接进入到 CedarAndroidLib 目录下&#xff0c;也即此例中的 frameworks/av/media/CedarX-Projects/CedarAndroidLib。看一下当前文件&#xff1a; 注意第9行为包含标题中报错…

《言简意赅之Linux设备驱动编程》 前言

linux 内核与驱动开发是一门很深的学问&#xff0c;主要是由于覆盖知识面较广、内核架构设计层级较深、软硬件知识要兼具。因此自己在学习理解时会经常遇到某一章节需要反复阅读理解多次。所以&#xff0c;我想用一种言简意赅的方式讲述 Linux 内核与设备驱动开发。我认为把一个…

Windows与Linux下tftp服务的使用

tftp 协议是基于 udp 的&#xff0c;轻量小巧&#xff0c;用在局域网和嵌入式上很顺手。大部分帖子把在 linux 上配置的过程描述的过于复杂&#xff0c;其实只是个工具而已。研究协议抓下包对比协议内容也可以满足需求了&#xff0c;下面进入正文。分别讲下在 linux 以及 windo…

Vmware提示:the operation was canceled by the user

一般遇到这种情况是由于当前虚拟机资源中的资源文件被其他进程占用导致的。如果你的系统中有 DAEMON Tools Lite 软件&#xff0c;那么多半是因为这个原因。因此下面针对此情况提出两种解决办法&#xff1a; 1. 检查有无安装 DAEMON Tools Lite 软件&#xff0c;若安装此程序&a…

USB OTG 的进一步理解

一直以来在做安卓系统相关的嵌入式通讯&#xff08;USB、BLE、网络、串口等&#xff09;&#xff0c;最近在讨论 OTG 问题的时候&#xff0c;对该规范又重新理解了一次&#xff0c;这里仅做一些概要和核心点说明&#xff0c;下方会给出具体 OTG 包含协议的参考链接&#xff0c;…

中标麒麟/NeoKylin U盘安装系统

这里以 NeoKylin6 为例&#xff0c;其他版本与此相类似大同小异。但是下载指定版本的镜像时要注意配合该版本的软件包是否充足&#xff0c;不然就会遇到安装好系统很多软件无法安装或更新的情况。 1. 官方下载地址&#xff1a;http://download.cs2c.com.cn/neokylin/desktop/re…