Android USB 支持两种模式:1. 主机模式;2. 配件模式;这里我们主要梳理HOST模式的使用;
USB 模块的使用可参考官方文档:
USB 主机和配件概览 | Android 开发者 | Android Developers (google.cn)
来声明需要使用 android.hardware.usb.host
intent-filter
来声明接收USB设备连接的通知;
<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 文件:
<resources>
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
resources>
如果您想过滤某个特定设备,请使用供应商 ID 和产品 ID;如果您想过滤一组 USB 设备(例如大容量存储设备或数码相机),请使用类、子类和协议。您可以指定所有这些属性,也可以不指定任何属性。如果不指定任何属性,则会与每个 USB 设备进行匹配
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
UsbDevice device = deviceList.get("deviceName");
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);
}
}
}
}
};
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);
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
}
}
}
};
close()
来关闭 UsbInterface
和 UsbDeviceConnection
。