android USB host APIs中文翻译

1 篇文章 0 订阅
1 篇文章 0 订阅

USB host APIs中文翻译

当你的Android设备处于USB主机模式下,它作为USB主机,为总线供电,并枚举已连接的USB设备。USB主机模式仅在Android3.1和更高版本下支持。 

1、API概述 

在开始之前,理解你所需要使用的类是非常重要的。下表描述了android.hardware.usb包中的USB host API。 

表1 USB host API

说明
UsbManager允许您枚举并与已连接的USB设备进行通信。
UsbDevice表示一个已连接的USB设备,并包含一些方法来访问它的识别信息,接口和端点。
UsbInterface表示USB设备的一个接口,该设备定义了一组功能。一个设备可以具有在其上进行通信的一个或多个接口。
UsbEndpoint表示一个接口的端点,这是该接口的通信信道。一个接口可以有一个或多个端点,并且为了与设备双向通信,通常具有输入和输出端点。
UsbDeviceConnection表示与设备的连接,该设备在端点上传输数据。这个类允许你同步或异步的发送和回传数据。
UsbRequest表示一个异步请求,他通过UsbDeviceConnection与设备进行通信。
UsbConstants定义USB常量,对应于定义在Linux内核中的linux/usb/ch9.h。








在大多数情况下,与USB设备通信需要使用所有的这些类(UsbRequest类只有进行异步通信时需要)。一般情况下,你使用UsbManager类以检索所需的UsbDevice。当你有检索到该设备,你需要找到合适的UsbInterface和位于接口上的UsbEndpoint来进行通信。一旦你获得正确的端点,打开一个UsbDeviceConnection完成与USB设备的通信。

2、Android清单要求

下面的列表描述了在使用USB host APIs之前,您需要在应用程序清单文件(AndroidManifest.xml)中添加哪些内容:

2.1、因为并不是所有的Android设备都保证支持USB host APIs,你需要包含一个<uses-feature>元素,来声明你的应用程序使用了android.hardware.usb.host功能。
2.2、设置应用程序的最低SDK API级别为12或更高。更早的API级别不存在USB host APIs。
2.3、如果想要应用程序在有USB设备连接时获得通知,需要在主activity中同时指定<intent-filter>和<meta-data>元素,来表明android.hardware.usb.action.USB_DEVICE_ATTACHED 意图(intent)。<meta-data>元素指向一个的外部XML资源文件,其声明了有关你要检测的设备的识别信息。
在XML资源文件中,为你要筛选的USB设备声明<usb-device>元素。下面的列表描述<usb-device>中的属性。一般情况下,利用供应商(VID)和产品ID(PID)来筛选一个特定设备 ,使用类、子类,制定协议来筛选一组USB设备,例如大容量存储设备或数码相机。您可以指定不含任一属性,或所有属性。不指定任何属性将与所有USB设备相匹配,所以只当你的程序需要它时来指定:
·厂商ID(vendor-id)
·产品ID(product-id)
·类(class)
·子类(subclass)
·协议(protocol 设备或接口)
将这些资源文件保存在res/XML目录下。资源文件名(不带扩展名.xml )必须与<meta-data>元素中指定的保持一致。XML资源文件的格式示例如下。

3、清单和资源文件的例子 

下面的例子显示了一个样例清单及其对应的资源文件:
<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>

4、与设备工作

当用户将USB设备连接到Android设备时,Android系统可以判断你的应用程序是否对连接的设备感兴趣。如果是,你可以与设备建立通信,如果需要的话。要做到这一点,你的应用程序需要: 
·通过使用一个意图过滤器,在用户接入一个设备时获得通知,或通过枚举那些已经连接的USB设备来发现USB设备。
·向用户请求连接到USB设备的许可,如果尚未取得的话。 
·通过在相应接口端点上读和写数据来与USB设备通讯。

5、发现设备

您的应用程序可以通过使用一个意图过滤器,在用户接入一个设备时获得通知,或通过枚举那些已经连接的USB设备来发现USB设备。如果你希望能够让应用程序自动检测所需的设备,使用一个意图过滤器是非常有用的。如果你想获得所有接入设备的列表,或者应用程序没有过滤意图,那枚举已连接的USB设备是非常有用的。

5.1、使用意图过滤器

为了使应用程序发现一个特定的USB设备,您可以指定一个意图过滤器,来过滤android.hardware.usb.action.USB_DEVICE_ATTACHED意图。和这个意图过滤器一起,你需要指定一个资源文件,用来指定USB设备属性,如产品和供应商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);

5.2、枚举设备 

如果你有兴趣在应用程序运行时检查所有当前已连接的USB设备,它可以在总线上枚举设备。使用getDeviceList()方法来获取所有已连接的USB设备的哈希映射。如果你想从哈希映射上获取设备,使用USB设备的名称来获得键值。
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
}

6、获得通信权限

在与USB设备通信之前,你的应用程序必须从用户组获得权限。
注意:如果您的应用程序使用一个意图过滤器来发现设备(如果已经连接),并且用户允许应用程序处理意图,那么权限是自动获得的。如果没有,你必须在连接设备之前,在应用程序里明确请求权限。


明确要求权限在某些情况下可能是必须的,例如当应用程序枚举已经连接的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) {
                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 extra(这是一个表示结果的布尔值)的意图。在连接到设备之前,检查这个extra是否为真。

7、与设备通讯

与USB设备通信可以是同步或异步的。不论哪种方式,你都应该创建一个线程,在它之上进行所有的数据传输,这样你就不会阻塞UI线程。为了与设备正确的建立通信,你需要获得你想要与之通讯的设备的UsbInterface和UsbEndpoint,然后在此端点上通过UsbDeviceConnection发送请求。一般情况下,你的代码应该:
·检查UsbDevice对象的属性,如产品ID ,供应商ID或设备类,来确认是否要与该设备进行通信。
·当您确定要与该设备进行通信,找到你想要用来通讯的相应UsbInterface,同样还有该接口下的的相应UsbEndpoint。接口可以有一个或多个端点,并且通常为双向通信,会有一个输入端点和输出端点。
·当你找到了正确的端点,在该端点打开一个UsbDeviceConnection 。
·提供您想要在端点上通过bulkTransfer()或controlTransfer()方法传输的数据。你应该在另一个线程执行此步骤,以防止阻塞主UI线程。如需在Android使用线程的更多信息,请参见Processes和Threads。
下面的代码片段是实现同步数据传输的一个简单方式。你的代码应该有更多的逻辑来正确地找到通讯所在的正确接口和端点,也应当在主UI线程以外的其他线程进行任何数据的传输:
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类来初始化和排队异步请求,然后用requestWait()等待结果。 

欲了解更多信息,请参阅AdbTest范例,它展示了如何实现异步批量传输;MissleLauncher范例,它演示了如何在一个中断端点进行异步监听。 

8、终止与设备的通信 

当您完成与设备的通讯,或者设备被拔出,通过调用releaseInterface()和close()来关闭UsbInterface和UsbDeviceConnection。要监听设备离线事件,请创建一个广播接收器(如下):
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
            }
        }
    }
};
在应用程序内创建广播接收器,而不是清单,这种方式会让您的应用程序只有在运行时才处理设备离线事件。这样一来,设备离线事件只会发送到当前正在运行的应用程序,而不是广播到所有的应用程序。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值