android USB通信
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并且驱动总线。
imageUSB 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();* } } };
更多相关文章
- 【阿里云镜像】切换阿里巴巴开源镜像站镜像——Debian镜像
- [Android] Nexus 7 二代连接 Windows 7
- Android应用开发提高系列(5)——Android动态加载(下)——加载已安装A
- 【Android休眠】之Android对PowerKey事件的处理(2)EventHub
- Android(安卓)LayoutInflater的获取及inflate()参数和返回值
- AnDroidDraw.apk的安装
- Xamarin.Android使用教程之在Android和Xamarin Android(安卓)Vis
- Android(安卓)adb shell刷机命令实战
- Android利用NotificationListenerService实现消息盒子功能