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并且驱动总线。

android USB通信_第1张图片
image

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();
*
            }
        }
    };

你可能感兴趣的:(android USB通信)