安卓USB通信

1 引言

  随着安卓手机的市场份额逐步增加,安卓系统的功能也日益强大。使用手机与各类设备通信的场景也越来越多,本篇文章将介绍如何使用安卓手机与USB设备进行通信。

2 USB简介

  USB是英文Universal Serial Bus(通用串行总线)的缩写,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在PC领域的接口技术。现在智能手机也加入了对于USB设备的支持。安卓手机支持USB accessory模式和USB host模式。USB host模式是手机充当主机,为总线提供电力支持。USB accessory模式正好相反,将手机当作附件把USB设备当作主机。本文中介绍的为Host模式。

3 相关API

class 说明
UsbManager USB管理器,与连接的USB设备通信。
UsbDevice USB设备的抽象,每个UsbDevice都代表一个USB设备。
UsbInterface 定义了设备的功能集,一个UsbDevice可能包含一个或多个UsbInterface,每个Interface都是独立的。
UsbEndpoint UsbEndpoint是Interface的通信通道。
UsbDeviceConnection host与device 建立的连接,并在endpoint 传输数据。
UsbRequest USB 请求包。
UsbConstants USB常量的定义

4 通信流程

4.1 配置AndroidManifest.xml文件

<!--添加权限-->
<uses-feature android:name="android.hardware.usb.host"/>

<activity
            android:name=".MainActivity"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <!-- 如果这里是启动Activity的话,点击USB接入的弹窗会启动该页面 -->
                <category android:name="android.intent.category.LAUNCHER" />
                <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>

4.2 过滤设备

  在XML资源文件中,声明要过滤的USB设备的元素。以下列表描述了属性 。通常,如果要过滤特定设备并使用类,子类和协议(如果要过滤一组USB设备(如大容量存储设备或数码相机)),请使用供应商(vendor-id)和产品(product-id)ID,在开发中这些过滤ID一般可以在文档中找到,或者自己连上看也行。你可以指定部分或全部这些属性。
  将资源文件保存在res/xml/目录中。资源文件名(不带.xml扩展名)必须与您在元素中指定的文件名相同 。

配置格式如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device
        class="255"
        product-id="5678"
        protocol="1 "
        subclass="66"
        vendor-id="1234" />
</resources>

pid与vid的获取可以通过设备管理器查看。

4.3 监听USB设备的插拔

  Android 系统中,USB 设备的插入和拔出是以系统广播的形式发送的,我们只要注册监听这个广播就好

public class USBReceiver extends BroadcastReceiver {
    public static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    @Override
    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 (device != null) {
                    //call method to set up device communication
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        Log.e("USBReceiver", "获取权限成功:" + device.getDeviceName());
                    } else {
                        Log.e("USBReceiver", "获取权限失败:" + device.getDeviceName());
                    }
                }
            }
        }else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            // 有新的设备插入了,在这里一般会判断这个设备是不是我们想要的,是的话就去请求权限
        } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            // 有设备拔出了
        }
    }
}

4.4 获取UsbManager

  UsbManager类通过获取系统服务的方式获取。

usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

4.5 获取目标UsbDevice

目标USB设备通过设备的pid和vid区别。
```

/**
 * @param vendorId  厂商ID
 * @param productId 产品ID
 * @return  device
 */
public UsbDevice getUsbDevice(int vendorId, int productId) {
top Created with Sketch.