安卓USB模块分析(二)- API使用

Android USB 支持两种模式:1. 主机模式;2. 配件模式;这里我们主要梳理HOST模式的使用;

USB 模块的使用可参考官方文档:

USB 主机和配件概览  |  Android 开发者  |  Android Developers (google.cn)

使用流程总结

  1. 发现连接的 USB 设备,具体方法是使用 Intent 过滤器在用户连接 USB 设备时接收通知,或者枚举已连接的 USB 设备。
  2. 请求用户授予连接到 USB 设备的权限(如果尚未获得权限)。
  3. 通过在适当的接口端点读取和写入数据来与 USB 设备通信。
  4. 完成通信或设备断开后释放资源。

配置清单文件

  1. 使用 <uses-feature> 来声明需要使用 android.hardware.usb.host
  2. 通过 intent-filter 来声明接收USB设备连接的通知;
    1. 通过 action 声明通知类型
    2. 通过 meta-data 声明感兴趣的设备(过滤);
<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>  

device-filter 文件:

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

如果您想过滤某个特定设备,请使用供应商 ID 和产品 ID;如果您想过滤一组 USB 设备(例如大容量存储设备或数码相机),请使用类、子类和协议。您可以指定所有这些属性,也可以不指定任何属性。如果不指定任何属性,则会与每个 USB 设备进行匹配

获取设备

  1. 获取触发设备
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
  1. 枚举设备
    通过 getDeviceList 方法来枚举设备:
    UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
    ...
    HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
    UsbDevice device = deviceList.get("deviceName");

申请通信权限

  1. 如果应用使用 Intent 过滤器来发现已连接的 USB 设备,则它会在用户允许应用处理 Intent 时自动获得权限。否则,必须在应用中明确请求权限,然后才能连接到设备。
  2. 手动申请权限
  3. 创建广播接收器
    private static final String ACTION_USB_PERMISSION =
        "com.android.example.USB_PERMISSION";
    private final BroadcastReceiver usbReceiver = 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);
                    }
                }
            }
        }
    };
  1. 注册广播接收器:
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    private static final String ACTION_USB_PERMISSION =
        "com.android.example.USB_PERMISSION";
    ...
    permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    registerReceiver(usbReceiver, filter);
  1. requestPermission
    UsbDevice device;
    ...
    usbManager.requestPermission(device, permissionIntent);

当用户在该对话框中作出回复时,广播接收器会收到包含 EXTRA_PERMISSION_GRANTED extra 的 Intent,即表示回答的布尔值。在连接到设备之前,需要检查此 extra 的值是否为 true。

设备通信

与 USB 设备的通信可以是同步的,也可以是异步的。在两种情况下,都应该创建一个新线程来执行所有数据传输,这样就不会锁定UI线程。要正确设置与设备的通信,需要获取要与之通信的设备的相应 UsbInterface 和 UsbEndpoint,并使用 UsbDeviceConnection 在此端点发送请求。通常,您的代码应该执行以下操作:

  • 检查 UsbDevice 对象的属性(例如产品 ID、供应商 ID 或设备类别),判断您是否要与设备通信。
  • 在您确定要与设备通信时,找到您要用于通信的适当 UsbInterface 以及该接口的适当 UsbEndpoint。接口可以具有一个或多个端点,并且通常具有用于双向通信的输入和输出端点。
  • 找到正确的端点后,在该端点上打开 UsbDeviceConnection
  • 使用 bulkTransfer() 或 controlTransfer() 方法提供要在端点上传输的数据。您应该在另一个线程中执行此步骤,以防止主界面线程被锁定。如需详细了解如何在 Android 中使用线程,请参阅进程和线程

同步数据传输

  private Byte[] bytes;
  private static int TIMEOUT = 0;
  private boolean forceClaim = true;

  UsbInterface intf = device.getInterface(0);
  UsbEndpoint endpoint = intf.getEndpoint(0);
  UsbDeviceConnection connection = usbManager.openDevice(device);
  connection.claimInterface(intf, forceClaim);
  //do in another thread
  connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); 

异步数据传输

使用 UsbRequest 类以 initialize 和 queue 异步请求,然后使用 requestWait() 等待结果。

如需了解详情,请参阅 AdbTest 示例(展示了如何执行异步批量传输)和 MissileLauncher 示例(展示了如何异步监听中断端点)。

终止通信

  • 监听断开连接事件,创建如下广播接收器:
 BroadcastReceiver usbReceiver = 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
                }
            }
        }
    };
  • 当完成与设备的通信或者设备断开连接后,调用 releaseInterface() 和 close() 来关闭 UsbInterface 和 UsbDeviceConnection
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值