翻译Android USB HOST API

时间:2023-01-29 08:33:00

翻译Android USB HOST API

源代码地址:http://developer.android.com/guide/topics/connectivity/usb/host.html

译者注:翻译的好不好不是太重要,重点是在翻译的过程中会把每句话都看认真看一遍,或者说是抱着翻译的思想来完毕一个读懂的目的。

USB Host通信

当你的可供电Android设备处理USB host模式时,它担任着为USB总线供电,枚举连接的USB从设备等等一个主设备应用的工作。

Android 3.1及以后版本号開始支持USB host模式。

API概述

開始之前,有必要弄明确以后要用到的类。下表中描写叙述了包括在android.hardware.usb包中的USB host APIs。

表1. USB host APIs.

Class

Description

UsbManger

同意你枚举USB从设备以及和其通信

UsbDevice

代表一个USB从设备,获取其信息。

如接口,端点等等。

UsbInterface

代表一个USB从设备的接口,一个设备能够拥有多个接口用于通信。

UsbEndpoint

代表接口的一个端点。它是该端点一个通信通道。

一个接口能够拥有一个或者多个端点,通常输入输出端点用于和设备进行双向通信。

UsbDeviceConnection

代表一个设备的连接,通过端点数据传输,该类同意你发送接收数据,通信方式能够是同步或者异步。

UsbRequest

代表通过UsbDeviceConnection通信的异步请求。

UsbConstants

定义USB常量相应Linux内核中linux/usb/ch9.h中的宏。

多数情况下。在和USB设备进行通信的时候,你须要使用这里全部的类(UsbRequest仅仅用在异步通信一个请求)。

通常是这种,使用UsbManager来获取UsbDevice。确定了设备。须要查找用于通信接口的UsbInterfaceUsbEndpoint。一旦获取了恰当的端点。打开UsbDeviceConnection与USB设备进行通信。

下列表中描写叙述了使用USB host APIs之前须要加入到应用程序的manifest文件里的内容:

因为并非全部的Android带供电设备确保支持USB host APIs,加入 <uses-feature>对象来表明你的应用使用了android.hardware.usb.host特性。

SDK最低版本号设置为12或者更高。USB host APIs不支持更老版本号的API。

假设你想让你的应用检測一个USB设备的话,在主Activity指定 <intent-filter> 和<meta-data> 对象去匹配android.hardware.usb.action.USB_DEVICE_ATTACHED。

<meta-data>对象指向一个外部的XML资源文件,文件里描写叙述你想要探測的USB设备的过滤信息。

在这个XML资源文件里,为你想要过滤的USB设备声明<usb-device>对象。

下列表中描写叙述了<usb-device>的属性。

通常,使用vendor 和 product ID过滤特殊设备。使用类。子类和协议来过滤一组设备。比方大容量存储设备(优盘)或者数码相机。你能够全然指定这个属性值。也能够一个也不指定。没有属性值说明会过滤每一个一个USB设备。所以说。你的应用程序有这个需求的情况下能够指定。

  • vendor-id
  • product-id
  • class
  • subclass
  • protocol (device or interface)

保存资源文件到res/xml/文件夹下。资源文件名称(不包括.xml后缀)必需要和<meta-data>中指定的同样。

XML资源文件格式假设下面演示样例:

<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上时,不管你的应用程序是否对此USB设备感兴趣Android系统都会检測到。

你能够和设备建立通信。你的应用程序须要做例如以下事情:

1.探測USB设备通过意图过滤器检測用户连接的设备。或者枚举已经连接的USB设备。

2.假设之前没有请求过,向用户请求权限以连接USB设备。

3.和USB设备进行通信。通过接口端点读写数据。

探測设备

应用程序能够通过两种方式进行USB设备的探測,使用意图过滤器监听用户连接设备或者枚举已经连接的USB设备。

前者能够方便的实现自己主动检測设备。

假设想列出全部的已连接设备或者没有使用意图过滤器过滤的设备,能够使用枚举设备来完毕。

使用意图过滤器

探測设备能够指定意图过滤器来过滤android.hardware.usb.action.USB_DEVICE_ATTACHED意图。此外须要指定一个资源文件描写叙述USB设备,比方product and vendor ID. 当用户连接上和你探測的设备匹配时,系统会弹出一个对话框询问用户是否同意启动的你的应用程序。假设同意,你的应用程序将会自己主动被赋予权限和该设备通信,直到设备被移除。

下面演示样例显示怎样描写叙述意图过滤器:

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

在你的Activity中。你要获得UsbDevice,它代表使用意图探測到的设备。如:

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

枚举设备

在你的应用程序执行时,假设对所以当前正在连接的USB设备感兴趣。能够枚举设备。枚举设备使用的是getDeviceList()方法获取全部连接设备的哈希表。假设你想获取一个设备能够依据USB设备的名字为keyword进行索引。

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

必要时,你从哈希表中迭代设备依次处理每一个设备:

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设备,假设用户同意处理意图,那么你的应用程序自己主动会获取权限。

反之,通信之前你必须向用户请求权限。

在一些情况下请求权限是必须的,比如你的应用程序枚举已经连接的USB设备以及与设备通信。通信之前你须要检查权限。否则假设用户权限拒绝你将会收到一个执行错误。

申请权限。首先创建创建一个广播接收器。

调用requestPermission()时,接收器监听广播意图。调用requestRermission()向给用户显示一个对话框请求连接该设备的权限。

下列代码显示怎样创建这样一个广播接收器:

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);
                }
            }
        }
    }
};

加入例如以下代码到activity的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意图。它是一个布尔代表答案。通信之前检查这个额外值是否为真。

与设备通信

通信方式能够是同步或者异步。

在这两种情况下,你应该创建一个线程运行全部数据的传输。不要堵塞界面线程。

建立一个通信。你须要获取须要通信设备的UsbInterfaceUsbEndpoint,以及使用UsbDeviceConnection申请端点。一般地,你的代码应该是:

  • 检查UsbDevice对象的属性,比方 product ID, vendor ID或者设备类别。以识别是不是须要通信的设备。
  • 假设确定了是要通信的设备,检索出你须要通信设备的接口。以及该接口的端点。接口能够有一个或者多个端点,通常会有输入输出各一的双向通信的端点。
  • 假设确定了端点。在该端点上打开 UsbDeviceConnection
  • 使用bulkTransfer()或者controlTransfer()方法将须要传输的数据提供到端点上。

    你须要将上述操作实如今其他线程以免堵塞当前主界面线程。

    很多其他关于Android中线程的使用,见Processes and Threads.

以下的代码片段简单的实现了同步传输数据。

你的代码应该使用很多其它逻辑上的来查找出正确的通信接口和端点,相同须要在主界面以外的线程中进行数据的传输:

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()等待结果。

很多其它信息见AdbTest样例,它显示了怎样进行块传输的方法异步通信。以及MissleLauncher sample它显示了怎样监听中断端点异步。

终止通信

当完毕了通信或者设备被移除了,调用releaseInterface()close()来关闭UsbInterfaceUsbDeviceConection。监听设备移除事件,创建一个广播接收器例如以下:

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中。仅在应用程序程序执行时处理设备移除事件。

如此,移除事件仅仅会发送给正在执行的应用而不是全部的应用。

感悟:

  • 与原文无关纯属个人感想,USB通信越向下越复杂。

    Android封装好一些,其次是libusb。再然后就是Linux内核中进行的USB通信。依次须要了解的知识多少都不一样,比方这个完整的通信过程中并没实用到urb等等。

  • 眼下測试的Android4.2.2上通信的最大块为:16KiB。所以数据要切割为16KiB大小进行传输。
  • 文件里提到的那个样例AdbTest和MissleLauncher的源代码位于:development/samples/USB/中。前者功能是读取usb设备(相同也是Android系统)的LOG,后者功能是控制一个火箭发射器玩具。
  • Android这套API并不能检測全部的USB设备,有些设备检測不到。比方无线数据的适配器。眼下測试成功的有打印机。
  • 关于对其了解的程度,我一直有个毛病就是了解一个东西没有上限。类似写文章没有主线。想到哪里就深入到哪里。我要逐渐改点这个习惯。

    我对这个的练习是将数据发送打印机。完毕打印。当我刚刚实现的时候,我就又開始幻想我是不是能够做一个非常牛叉的USB打印APP了。这个是能够实现的,但并非眼下的主要任务,假设我坚持做。非常多东西都须要去实现。这也违背了我当前不过了解Android USB host API的初衷。还好,这次我刹住了闸。毕竟我这次是真实的了解了,之前只知道在Linux内核中的通信以及基于Libusb通信,直接使用java通信的优点是解析xml等等在C语言中相对复杂的东西到java中都不显示复杂了。

  • l 測试APK和上文提到的那两个样例打包上传到Here,方便那些没有Android系统源代码的同志。

翻译Android USB HOST API的更多相关文章

  1. Android USB Host与HID通讯 &lpar;二&rpar;

    不好意思,从上一篇到现在确实比较忙,中间又外出了一段时间,虽然也上LOFTER,或者看到一些朋友QQ上加我,给我发信息询问,有些看到了有些可能没看到,偶尔回复了一两个,也不咋的详细,在此我想说,一方面 ...

  2. Android USB Host与HID通讯 &lpar;一&rpar;

    去年9月份来到现在的公司,接到新公司的第一个项目就是Android USB Host与HID通讯,当时也什么都不懂,就拿着google的api 开发指南 (http://developer.andro ...

  3. Android USB Host与HID通讯

    前端时间捣鼓一个HID的硬件, 需要和android通信, 网上搜索了一圈,收获不小. 比较好的文章是:      Android USB Host与HID通讯 Android Service创建US ...

  4. Android USB Host 与 Hid 设备通信bulkTransfer&lpar;&rpar;返回-1问题的原因

    近期一直在做Android USB Host 与USB Hid设备(STM32FXXX)的通信,遇到了很多问题.项目源码以及所遇到的其他问题可以见本博客其他相关文章,这里重点讲一下bulkTransf ...

  5. Android USB Host 与 HID 之通讯方法

    Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两个方法,要实现真正的通 ...

  6. Android USB Host 与 HID 之通讯方法&lpar;bulkTransfer&lpar;&rpar;与controlTransfer&lpar;&rpar;方法使用&rpar;

    转载地址:差满多乃几 Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两 ...

  7. 『翻译』Android USB Host

    USB Host When your Android-powered device is in USB host mode, it acts as the USB host, powers the b ...

  8. android usb host 读写USB设备

    自android3.1以后android增加了操作USB设备的API. 官网地址:http://developer.android.com/guide/topics/connectivity/usb/ ...

  9. android usb Host模式下与usb Hid 设备的通信

    做android 与USB HID设备的通信有段时间了,总结一下遇到的问题和解决方法: 1,第一次遇到的问题:android 版本低不支持usb hid, 被要求做相关项目的时候,就从mUsbMana ...

随机推荐

  1. ecliplse高亮显示选中的相同变量

    选择:windows-> preferences->java->Editor->Mark Occurences 选择最上的复选框,下面的就有很多了. 其中的Local vari ...

  2. Windows消息机制知识点总结

    1.windows消息类型 以下四种,前三种是系统消息,范围在[0x0000, 0x03ff],第四种是用户自定义消息. 1.1 窗口消息 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等.可以 ...

  3. 安装python的pywin32安装不了,提示找不到py3&period;6-32

    安装python的pywin32安装不了,提示找不到py3.6-32 首先我自己的py3.6是64位版本的,这是pywin32模块的下载地址 里面有各种版本的,首先我先下了64位的3.6版本的,结果提 ...

  4. TXLSReadWriteII5 单元格读写

    unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ...

  5. &lbrack;UE4&rsqb;隐藏对象Set Visibility

    Propagate to Children:是否遍历子对象(用来设置子对象可见性)

  6. C&num;图像处理&colon;Stream 与 byte&lbrack;&rsqb; 相互转换,byte&lbrack;&rsqb;与string,Stream 与 File 相互转换等

    C# Stream 和 byte[] 之间的转换 一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Ima ...

  7. IP概念盛行的背后:资本在狂欢,电影想哭泣 IP,英文&OpenCurlyDoubleQuote;Intellectual Property”的缩写,直译为&OpenCurlyDoubleQuote;知识产权”。它的存在方式很多元,可以是一个故事,也可以是某一个形象,运营成功的IP可以在漫画、小说、电影、玩具、手游等不同的媒介形式中转换。

    IP概念盛行的背后:资本在狂欢,电影想哭泣 IP容易拉投资.谈合作,甚至还能简化宣发途径,越来越多的人涌入了电影这个产业,争抢IP成为他们进入行业的最快捷的方法.IP盛行暴露出的另一个问题是国产电影原 ...

  8. Java多线程的下载器(1)

    实现了一个基于Java多线程的下载器,可提供的功能有: 1. 对文件使用多线程下载,并显示每时刻的下载速度. 2. 对多个下载进行管理,包括线程调度,内存管理等. 一:单个文件下载的管理 1. 单文件 ...

  9. POJ 2253 Frogger(dijkstra变形)

    http://poj.org/problem?id=2253 题意: 有两只青蛙A和B,现在青蛙A要跳到青蛙B的石头上,中间有许多石头可以让青蛙A弹跳.给出所有石头的坐标点,求出在所有通路中青蛙需要跳 ...

  10. bzoj1069&colon; &lbrack;SCOI2007&rsqb;最大土地面积 凸包&plus;旋转卡壳求最大四边形面积

    在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. 题解:先求出凸包,O(n)枚举旋转卡壳,O(n)枚举另一个点,求最大四边形面积 /* ...