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. Linux 服务器CPU占用率100%,使用率高解决方案

    机器高负载告警一般是CPU负载在99-100%,同时伴有大量的网络出包和入包量,常见的原因是机器在某个时段进行LOG,数据等备份操作,或者服务器被黑导致 输入top命令查看CPU使用情况 top 通过 ...

  2. express下使用ES6

    //环境切换配置 package.json scripts:{ "service": "NODE_ENV=production PORT=3000 npm start&q ...

  3. [LeetCode] 295. Find Median from Data Stream 找出数据流的中位数

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

  4. Ubuntu16.04 安装搜狗Linux中文输入法

    参考链接: https://blog.csdn.net/leijieZhang/article/details/53707181 补充:安装完搜狗拼音输入法后候选栏是乱码的情况,解决方法如下: 输入如 ...

  5. .Net Core 1.1 + CentOs 7 环境配置

    centos7下使用yum安装mysql5.7.10 参考:http://www.cnblogs.com/hwd-cnblogs/p/5213337.html http://www.jb51.net/ ...

  6. python使用consul进行服务注册和发现

    阅读目录 一.安装启动consul 二.python服务注册 三.golang服务注册 四.通过API的方式获取信息 回到顶部 一.安装启动consul 1.通过docker快速安装 #获取docke ...

  7. webpack打包完成,复制,打包,移动,删除已生成的文件插件

    const FileManagerPlugin = require('filemanager-webpack-plugin'); 详情请到 https://www.npmjs.com/ 一看究竟 贴个 ...

  8. 用ArcMap在PostgreSQL中创建要素类需要执行”create enterprise geodatabase”吗

    问:用Acmap在PostgreSQL中创建要素类需要执行"create enterprise geodatabase"吗? 关于这个问题,是在为新员工做postgresql培训后 ...

  9. POJ1166 The Clocks (爆搜 || 高斯消元)

    总时间限制: 1000ms,内存限制: 65536kB 描述 |-------| |-------| |-------| | | | | | | | |---O | |---O | | O | | | ...

  10. mysql left join和union结合的用法

    left join和union结合的用法子查询union 然后加个括号设置个别名 (union自动去除 重复的 ) <pre>select o.nickName,o.sex,o.provi ...