android USB通信

作者: yqyzxd | 来源:发表于2018-06-20 14:33 被阅读46次

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

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模式

<uses-feature android:name="android.hardware.usb.host"/>

获取UsbManager

UsbManager usbManager=(UsbManager)context.getSystemService(Context.USB_SERVICE)

获取目标UsbDevice

可以根据需求选择设备vid组合pid或设备deviceName寻找目标UsbDevice

String targetDeviceName="...";
UsbDevice targetDevice=null;
HashMap<String,UsbDevice> deviceMap=usbManager.getDeviceList();
Iterator<UsbDevice> 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<Byte> 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转串口通信

    一、引用 1、Git上最火的USB转串口通信2、Android之USB转串口通信3、安卓开发中的USB转串口通讯 ...

  • android USB通信

    USB模式 支持USB accessory模式和USB host模式。通过这两种模式,android支持各种各样的...

  • Android USB通信

    1:简介: 自Android3.1(API Level 12)版本开始,Android系统直接支持USB配件(A...

  • [Android]USB开发

    声明:主要参照文档:Android开发之USB数据通信安卓USB通信之权限管理 第一:请求权限和请求权限回调(通过...

  • Android USB通信与USB转串口通信

    前段时间公司有个项目,涉及Android BLE硬件通讯,需要用到Android USB转PL232、FD2...

  • Android USB OTG通信

    USB相关概念: 简单来说,USB 是一个用于数据交换的总线(Bus)。发启(initiate)数据交换的一方称为...

  • android usb串口通信

    引用 implementation'com.github.mik3y:usb-serial-for-android...

  • Android USB转串口通信

    最近需要在Android板卡上面对接些串口控制的外设,比如,4G模块、呼吸灯、光感传感器等,这些都是串口指令控制。...

  • Android USB 开发

    Android通过两种模式支持各种USB设备: USB accessory 和USB host。(Android ...

  • Mac上Android Studio调试Android手机

    Android调试桥( adb )是一个开发工具,帮助安卓设备和个人计算机之间的通信。 这种通信大多是在USB电缆...

网友评论

    本文标题:android USB通信

    本文链接:https://www.haomeiwen.com/subject/cvwtyftx.html