今天抽空整理一下上周开发USB Host过程中学习到的。Android USB通讯其实还是比较简单的,只要把具体的流程搞清楚,实现起来并不难。本文主要简单讲一下如何实现USB Host通讯以及在开发过程中遇到的问题。言归正传,在开发前,你需要做这么几件事情,首先你需要知道你要连接的USB设备的VID和PID,这里不再解释二者的含义(其实就是硬件ID);其次你需要清楚Android设备USB通讯的基本流程:获取硬件->枚举设备->找到设备接口->连接设备->分配相应端点->在IN/OUT端点进行数据的收发。

在清楚了这两点后,接下来就可以进行具体的代码书写了,和正常的通讯一样,USB Host也需要获取权限:

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

然后需要添加一个intent-filter和meta-data:

<!--过滤器,手动添加-->
 <intent-filter>
 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
 </intent-filter>
 <!--过滤集体的usb设备-->
 <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
 android:resource="@xml/device_filter"/>

相对应的device-filter.xml文件如下,其中添加的是设备的VID和PID,注意要区别的是此时的VID和PID均是16进制的,获取USB设备ID的方式很简单,在MAC下,可以从系统报告中获取,Windows下可以右键属性中获取,直接读到的就是16进制的,要主要如果此处是16进制,则在主要的代码中也需要是16进制,需要保持一致。

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <!--测试闪迪U盘-->
    <usb-device vendor-id="0781" product-id="5581" />
    <!--测试仪器-->
    <usb-device vendor-id="1204" product-id="4100" />
</resources>

接下来就是主代码的书写了。


public class UsbHost extends AppCompatActivity {
    private static final String TAG = "UsbHost";
    private UsbManager usbManager;   //USB管理器
    private UsbDevice mUsbDevice;  //找到的USB设备
    private UsbInterface Interface1, Interface2;
    private UsbDeviceConnection mDeviceConnection;
    private UsbEndpoint epOut, epIn;//定义Out/In端口
    private List<byte[]> list = new ArrayList<byte[]>();
    private List<RealMatrix> doubleTomatrix = new ArrayList<RealMatrix>();
    private int VID;
    private int PID;
    private Context applicationContext;
    private HexUtil hexUtil = new HexUtil();
    private CommonMath combineMatrix = new CommonMath();
    private RealMatrix averageMatrix;
    private int Datalength = 256;

    /**
     * 初始化设置
     */
    public UsbHost(int vid, int pid, Context context) {
        VID = vid;
        PID = pid;
        applicationContext = context;
        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);//获取设备硬件
        enumerataDevice();
        assignEndpoint(Interface1);
        openDevice(Interface1);
    }

    /**
     * 枚举设备
     */
    public void enumerataDevice() {
        //获取USB管理器,若获取失败,return
        if (usbManager == null) {
            return;
        } else {
            Log.i(TAG, "usb设备:" + String.valueOf(usbManager.toString()));
        }
        //通过对应设备映射到每一个设备名,一种存储机制
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        if (!deviceList.isEmpty()) {
            for (UsbDevice device : deviceList.values()) {
                //System.out.println(device.getVendorId()+"==="+device.getProductId()+device.getDeviceName());//1204===4100
                if (device.getVendorId() == 1204 & device.getProductId() == 4100) {
                    mUsbDevice = device;
                    getDeviceInterface();
                }
            }
        } else {

            Toast.makeText(applicationContext, "未找到设备,请先连接设备!", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 获取接口
     */
    private void getDeviceInterface() {
        if (mUsbDevice != null) {
//            System.out.println(mUsbDevice.getInterfaceCount() + "<----");
            for (int i = 0; i < mUsbDevice.getInterfaceCount(); i++) {
                UsbInterface intf = mUsbDevice.getInterface(i);
                if (i == 0) {
                    Interface1 = intf;//保存设备接口
                    Log.i(TAG, "成功获得设备接口:" + Interface1.getId());
                }
                if (i == 1) {
                    Interface2 = intf;
                    Log.i(TAG, "成功获得设备接口--->:" + Interface2.getId());
                }
            }
        } else {
            Toast.makeText(applicationContext, "UsbDevice实例为空", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * /*
     * 分配端点
     */
    private void assignEndpoint(UsbInterface mInterface) {// 分配端点
        if (mInterface != null) {
            //获取到端口,直接选择已知端口进行传输
            epOut = mInterface.getEndpoint(0);
            epIn = mInterface.getEndpoint(2);
        } else {
            Log.i(TAG, "Interface为空!");
        }
    }

    /**
     * 打开设备
     */
    private void openDevice(UsbInterface mInterface) {
        if (mInterface != null) {
            UsbDeviceConnection connection = null;
            //在open之前判断是否有连接的权限,对于连接权限可以静态分配,也可以动态分配权限
            if (usbManager.hasPermission(mUsbDevice)) {
                connection = usbManager.openDevice(mUsbDevice);
            }
            if (connection == null) {
                return;
            }
            if (connection.claimInterface(mInterface, true)) {
                mDeviceConnection = connection;
                /*
                * 内部判断设备是否为空,确认是否连接
                * */
                if (mDeviceConnection != null) {
                    Toast.makeText(applicationContext, "设备连接成功!", Toast.LENGTH_LONG).show();
                    Log.i(TAG, "openDevice找到!");
                } else {
                    Log.i(TAG, "无法开启连接通道");
                    connection.close();
                }
            } else {
                Log.i(TAG, "没有权限!");
            }
        }
    }
public double[] sendBytes() {//数据收发这部分需要仔细查看相关的设备信息
        double[] yData;
        byte[] Sendbytes = getCommand(5, 6,true);//发送指令,这个要根据具体的板子(USB设备)来测试
        int ret = mDeviceConnection.bulkTransfer(epOut, Sendbytes, Sendbytes.length, 500);//发送函数
        while (true) {
            byte[] Receivebytes = new byte[512];
            if (mDeviceConnection.bulkTransfer(epIn, Receivebytes, Receivebytes.length, 500) > -1) {//接收数据
                list.add(Receivebytes);
            } else break;//实现不连续接收数据
        }
        return yData;
    }
}