USB Accessory 模式
USB附件模式允许用户连接专为Android设备设计的USB主机硬件。配件必须遵守Android配件开发套件文档中概述的Android附件协议。这使得无法充当USB主机的Android电源设备仍然可以与USB硬件交互。当Android设备处于USB附件模式时,所附的Android USB附件充当主机,为USB总线供电,并列举连接的设备。 Android 3.1(API级别12)支持USB附件模式,并且该功能也被返回到Android 2.3.4(API级别10),以支持更广泛的设备

a. 选择正确的USB附件API
虽然USB附件API已经在Android 3.1平台上引入,但Android 2.3.4中也可以使用Google API附加库。因为这些API是使用外部库进行反向输入的,所以有两个包可以导入以支持USB附件模式。根据您要支持的Android驱动的设备,您可能需要使用其他设备:
com.android.future.usb:要在Android 2.3.4中支持USB附件模式,Google API附加库包括后端的USB附件API,它们包含在此命名空间中。 Android 3.1还支持在此命名空间中导入和调用类,以支持使用附加库编写的应用程序。这个附加库是围绕android.hardware.usb附件API的薄包装,不支持USB主机模式。如果要支持最广泛的支持USB附件模式的设备,请使用附加库并导入此软件包。重要的是要注意,并不是所有的Android 2.3.4设备都需要支持USB附件功能。每个设备制造商决定是否支持此功能,这就是为什么必须在清单文件中声明它。
android.hardware.usb:这个命名空间包含在Android 3.1中支持USB附件模式的类。该软件包作为框架API的一部分,所以Android 3.1支持USB附件模式而不使用附加库。如果您只关心具有USB附件模式硬件支持的Android 3.1或更新的设备,您可以在清单文件中声明,请使用此软件包。
b. API概述

UsbManager 允许您枚举和连接所连接的USB附件。
UsbAccessory 表示USB附件,包含访问其识别信息的方法。
如果您正在使用附加库,则必须以下列方式获取UsbManager对象:

UsbManager manager = UsbManager.getInstance(this);
1
如果您正在使用附加库,则必须以下列方式获取UsbManager对象:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
1
如果您不使用附加库,则必须以下列方式获取UsbAccessory对象:

UsbAccessory accessory = UsbManager.getAccessory(intent);
1
如果您不使用附加库,则必须以以下方式获取UsbAccessory对象:

UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
1
c. Android Manifest 要求
以下列表描述了在使用USB辅助API之前需要添加到应用程序的清单文件中。清单和资源文件示例显示如何声明这些项目:

因为并非所有Android设备都能保证支持USB附件API,还包括一个元素,声明您的应用程序使用android.hardware.usb.accessory功能。
如果您正在使用附加库,请添加指定库的com.android.future.usb.accessory的元素。
如果您正在使用附加库,请将应用程序的最小SDK设置为API Level 10,如果使用的是android.hardware.usb包,则将其设置为12。
如果希望您的应用程序被通知附加的USB附件,请在主要活动中为android.hardware.usb.action.USB_ACCESSORY_ATTACHED意图指定和元素对。 元素指向一个外部XML资源文件,它声明要检测的附件的信息。
在XML资源文件中,为要过滤的附件声明元素。每个可以具有以下属性:

manufacturer
model
version
1
2
3
将资源文件保存在res / xml /目录中。资源文件名(不含.xml扩展名)必须与您在元素中指定的文件名相同。 XML资源文件的格式也在下面的示例中显示

Manifest 和 resource 文件示例

<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在这种情况下,应将以下资源文件保存在res / xml / accessory_filter.xml中,并指定具有相应型号,制造商和版本的任何附件应被过滤。配件将这些属性发送给Android设备:

<?xml version="1.0" encoding="utf-8"?>
< resources>
< usb-accessory model="DemoKit" manufacturer="Google" version="1.0"/>
< /resources>
1
2
3
4
Working with Accessory
当用户将USB附件连接到Android设备时,Android系统可以确定您的应用程序是否对连接的附件感兴趣。如果是这样,如果需要,您可以设置与附件的通信。为此,您的应用程序必须:

1、通过使用过滤附件事件的意图过滤器或枚举连接的附件并找到适当的附件来发现连接的附件。
2、要求用户与附件通信,如果尚未获得。
3、通过在适当的接口端点上读取和写入数据来与附件通信。

Discovering an accessory
您的应用程序可以通过使用意图过滤器来发现附件,以便在用户连接附件或枚举已连接的附件时收到通知。如果希望能够让应用程序自动检测到所需的附件,则使用意图过滤器很有用。如果您想获得所有连接的配件的列表,或者您的应用程序没有为意图过滤,枚举连接的附件是有用的。

Using an intent filter
要使您的应用程序发现一个特定的USB附件,您可以指定一个intent过滤器来过滤android.hardware.usb.action.USB_ACCESSORY_ATTACHEDintent。除了该intent过滤器之外,还需要指定一个资源文件,该文件指定USB配件的属性,如制造商,型号和版本。当用户连接与您的附件过滤器相匹配的附件时,

以下示例显示如何声明intent过滤器:

< 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>
1
2
3
4
5
6
7
8
9
以下示例显示如何声明指定您感兴趣的USB附件的相应资源文件:

<?xml version="1.0" encoding="utf-8"?>

<resources>
<usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" />
</resources>
1
2
3
4
5
在您的活动中,您可以从这样的intent(使用附加库)获取代表附件的UsbAccessory:

UsbAccessory accessory = UsbManager.getAccessory(intent);
或者像这样(使用平台API):

UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
枚举 accessories

您的应用程序可以枚举在应用程序运行时识别自己的配件。
使用getAccessoryList()方法获取所有连接的USB附件的阵列:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbAccessory[] accessoryList = manager.getAcccessoryList();
获取与附件通信的权限

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

注意:如果您的应用程序使用意图过滤器在附件中发现附件,则如果用户允许您的应用程序处理意图,则它会自动接收权限。如果没有,您必须在连接到附件之前在应用程序中明确请求许可。

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

要明确获得许可,首先创建广播接收器。该接收器侦听当您调用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);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
};
要注册广播接收器,请将其放在您的活动中的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 extra的意图,这是一个表示答案的布尔值。在连接附件之前,请检查这个额外的值是否为true。

与 Accessory 通讯
您可以通过使用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();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在线程的run()方法中,您可以使用FileInputStream或FileOutputStream对象来读写附件。使用FileInputStream对象从附件读取数据时,请确保您使用的缓冲区足够大以存储USB数据包数据。 Android附件协议支持高达16384字节的数据包缓冲区,为了简单起见您可以选择始终声明缓冲区:

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

有关在Android中使用线程的更多信息,请参阅进程和线程。

终止与附件的通信

当您完成与附件的通信或附件脱离后,通过调用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
}
}
}
1
2
3
4
5
6
7
};
在应用程序中创建广播接收者,而不是清单,允许您的应用程序在运行时仅处理分离的事件。这样,分离的事件只会发送到当前运行的应用程序,而不是广播到所有的应用程序

USB Accessory 模式的更多相关文章

  1. [译] iOS 11.4.1 Beta:全新的USB限制模式

    (Source/原文链接 https://blog.elcomsoft.com/2018/06/ios-11-4-1-beta-usb-restricted-mode-has-arrived/) 作者 ...

  2. Android USB配件模式

    原文:http://android.eoe.cn/topic/android_sdk USB配件模式允许用户连接那些专门搭载Android设备的USB主机硬件.这些配件必须遵守Android配件开发工 ...

  3. 850 USB 烧录模式

    /************************************************************************* * 850 USB 烧录模式 * 说明: * 本文 ...

  4. 如何忽略usb host 模式设备连接确认对话框

    <li class="alt"><span><span>package android.hardware.usb;  </span> ...

  5. OPPO realme 2在哪里打开Usb调试模式的简单步骤

    每当我们使用PC通过数据线链接到安卓手机的时候,如果手机没有开启USB调试模式,PC则没能成功识别我们的手机,这时我们需要找解决方法将手机的USB调试模式开启,下文我们记录一下OPPO realme ...

  6. OPPO K3在哪里打开USB调试模式的完美方法

    当我们使用pc链接安卓手机的时候,如果手机没有开启USB调试模式,pc则无法成功识别我们的手机,这个时候我们需要找解决方法将手机的USB调试模式打开,今天我们介绍OPPO K3如何开启USB调试模式的 ...

  7. (详细)华为Mate7 MT7-TL00的usb调试模式在哪里开启的步骤

    就在我们使用pc连接安卓手机的时候,如果手机没有开启usb调试模式,pc则不能够成功识别我们的手机,在一些情况下,我们使用的一些功能较好的工具好比之前我们使用的一个工具引号精灵,老版本就需要打开usb ...

  8. OPPO A7x在哪里开启usb调试模式的详细经验

    当我们使用Pc连接安卓手机的时候,如果手机没有开启Usb调试模式,Pc则没法成功读到我们的手机,这时我们需要想办法将手机的Usb调试模式开启,这里我们讲解OPPO A7x如何开启Usb调试模式的方法. ...

  9. (最完美)MIUI12系统的Usb调试模式在哪里开启的步骤

    当我们使用安卓手机通过数据线链接到Pc的时候,或者使用的有些app比如我们公司营销小组当使用的app引号精灵,之前的老版本就需要开启usb调试模式下使用,现当新版本不需要了,如果手机没有开启usb调试 ...

随机推荐

  1. Docker搭建Kafka

    下载Kafka和Zookeeper镜像文件 1,docker pull wurstmeister/kafka 2,docker pull wurstmeister/zookeeper 先运行zk,再运 ...

  2. tomcat常见报错解决方法汇总

    报错一:内存泄漏,字眼This is very likely to create a memory leak. 解决方法:修改tomcat内存. 在tomcat/bin目录下,修改catalina.s ...

  3. AC与AP的安装使用(未经实战,仅供参考,未完待续)

    AC:无线控制器(Wireless Access Point Controller) AP:无线访问接入点(WirelessAccessPoint) 以信锐AC为例 AC设备的管理口为MANAGE(E ...

  4. [LeetCode] 151. Reverse Words in a String 翻转字符串中的单词

    Given an input string, reverse the string word by word. For example,Given s = "the sky is blue& ...

  5. Postman系列三:Postman中post接口实战(上传文件、json请求)

    一:接口测试过程中GET请求与POST请求的主要区别 从开发角度我们看get与post的主要区别是:1.Get是用来从服务器上获得数据,而Post是用来向服务器上传递数据:2.Get安全性比Post低 ...

  6. docker+k8s基础篇二

    Docker+K8s基础篇(二) docker的资源控制 A:docker的资源限制 Kubernetes的基础篇 A:DevOps的介绍 B:Kubernetes的架构概述 C:Kubernetes ...

  7. Java开发笔记(一百二十七)Swing的标签

    提起AWT的标签控件Label,那个使用体验可真叫糟糕,不但不支持文字换行,而且对中文很不友好,既可能把中文显示为乱码,还不支持博大精深的各种中文字体.所幸Swing的升级版标签JLabel在各方面都 ...

  8. 文件和异常——python从编程入门到实践

    从文件中读取数据 1. 读取整个文件 要读取文件,首先来创建一个文件: 然后打开并读取这个文件,再将其内容显示到屏幕上: file_reader.py with open('pi_digits.txt ...

  9. prometheus grafana graylog 钉钉告警 短信告警 电话告警系统 PrometheusAlert

    PrometheusAlert 简介 PrometheusAlert是开源的运维告警中心消息转发系统,支持主流的监控系统Prometheus,日志系统Graylog和数据可视化系统Grafana发出的 ...

  10. 最简单的centos上安装Nginx办法

    基本几个简单命令就能搞定 由于yum源中没有我们想要的nginx,那么我们就需要创建一个“/etc/yum.repos.d/nginx.repo”的文件,其实就是新增一个yum源. vi /etc/y ...