今天抽空整理一下上周开发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;
}
}