USB模式
支持USB accessory模式和USB host模式。通过这两种模式,android支持各种各样的USB 外围设备和USB 配件(硬件需要实现android配件协议)。
USB accessory模式中,外接的USB硬件设备扮演USB 主机,这种方式使不支持USB host模式的android设备有了与USB硬件交互的能力,不过android USB 配件必须遵循android accessory communication protocol。
在USB host模式下,android设备扮演主机角色。
下图展示的是两种模式的区别。在USB host模式下,android设备担任host并且驱动总线,在USB accessory模式下,连接的USB 硬件充当host并且驱动总线。
USB host模式使用
相关API
类 | 介绍 |
---|---|
UsbManager | 获取连接的USB设备并与之通信 |
UsbDevice | 代表一个连接的USB 设备,包含一系列方法获取自身信息,包括interfaces,endpoints |
UsbInterface | 代表USB 设备上定义的一系列功能接口,一个usb设备可以有一个或多个接口 |
UsbEndpoint | 代表一个interface通信频道,一个interface可以有一个或多个endpoints,一般含有输入输出两个端点来支持双工通信 |
UsbDeviceConnection | 代表设备连接的一个链路,将数据传输到端点上,这个类允许你同步或异步的来回发送数据 |
UsbRequest | 代表一个异步请求,通过UsbDeviceConnection来跟设备通信 |
UsbConstants | 定义了linux内核文件linux/usb/ch9.h中的常量 |
在绝大部分情况下,当你需要跟USB通信时,你需要用到这些类(UsbRequest类仅在异步通信时用到)。一般的,获取UsbManager找到目标UsbDevice,接着找到恰当的UsbInterface和这个interface的UsbEndpoint,得到了正确的UsbEndpoint后,打开设备获得UsbDeviceConnection来跟USB 设备通信。
代码步骤
android manifest配置
配置usb feature 是因为并不是所有的android设备都保证支持USB host模式
获取UsbManager
UsbManager usbManager=(UsbManager)context.getSystemService(Context.USB_SERVICE)
获取目标UsbDevice
可以根据需求选择设备vid组合pid或设备deviceName寻找目标UsbDevice
String targetDeviceName="...";
UsbDevice targetDevice=null;
HashMap deviceMap=usbManager.getDeviceList();
Iterator iterator=deviceMap.values().iterator();
while(iterator.hasNext()){
UsbDevice device=iterator.next();
if(targetDeviceName.equals(device.getDeviceName())){
targetDevice=device;
break;
}
}
申请USB使用权限
获取到UsbDevice后需要检查该UsbDevice是否已经获取到使用权限。如果没有权限则要申请USB使用权限,
if (!usbManager.hasPermission(usbDevice)) {
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
mContext.registerReceiver(mUsbPermissionReceiver, filter);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(usbDevice, pi);
}
private BroadcastReceiver mUsbPermissionReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_DEVICE_PERMISSION.equals(action)) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
boolean granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
if (granted) {
//获得了usb使用权限
usbDeviceInit(device);
}
}
}
};
获取UsbInterface以及对应得UsbEndpoints,UsbDeviceConnection
private void usbDeviceInit(UsbDevice device) {
int interfaceCount = device.getInterfaceCount();
UsbInterface usbInterface = null;
for (int i = 0; i < interfaceCount; i++) {
usbInterface = device.getInterface(i);
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_PRINTER) {
break;
}
}
if (usbInterface != null) {
//获取UsbDeviceConnection
UsbDeviceConnection connection = mUsbManager.openDevice(device);
if (connection != null) {
if (connection.claimInterface(usbInterface, true)) {
for (int j = 0; j < usbInterface.getEndpointCount(); j++) {
UsbEndpoint endpoint = usbInterface.getEndpoint(j);
//类型为大块传输
if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
mUsbEndpointOutMap.put(device.getDeviceName(), endpoint);
} else {
mUsbEndpointInMap.put(device.getDeviceName(), endpoint);
}
}
}
}
}
}
}
和USB设备通信
调用UsbDeviceConnection的bulkTransfer方法与USB设备通信,向USB设备发送数据用endpointOut,接受USB设备的数据用endpointIn。
private int bulk(String deviceName, ArrayList command) {
if (command!=null && !command.isEmpty()) {
UsbEndpoint endpointOut = mUsbEndpointOutMap.get(deviceName);
UsbDeviceConnection connection = mUsbDeviceConnectionMap.get(deviceName);
if (endpointOut == null || connection == null) {
return ErrorCode.CODE_ERROR;
}
byte[] data = new byte[command.size()];
for (int i = 0; i < command.size(); i++) {
data[i] = command.get(i).byteValue();
}
int ret = connection.bulkTransfer(endpointOut, data, data.length, TIME_OUT);//超时时间可以长一点,不然数据量大的时候容易超时错误
if (ret >= 0) {
return ErrorCode.CODE_SUCCESS;
}
return ErrorCode.CODE_ERROR;
}else {
return ErrorCode.CODE_SUCCESS;
}
}
USB设备插入,拔出通知
当USB设备插入或拔出时系统会发出相应的广播,因此注册这些广播就可以得到这些通知,然后进行相应的处理。
IntentFilter filter = new IntentFilter();
//注册USB设备插入,拔出动作
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager. ACTION_USB_DEVICE_DETACHED);
registerReceiver(receiver, filter);
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
//TODO 检查一个该device是否是我们的目标设备
if(!isTargetDevice(device)){
return
}
String action=intent.getAction();
if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
usbDeviceInit(device);
}else if(action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)){
/*TODO 释放UsbInterface 关闭UsbDeviceConnection
mUsbDeviceConnection.releaseInterface(interface);
mUsbDeviceConnection.close();
*
}
}
};