Android设备与USB设备的连接通讯
关于Android与USB设备的连接,所能搜索到的资料特别的少,但恰恰接到了一个这样的需求,使用android平板通过USB与一个外接设备进行通讯,这个设备是一个压力感应器,在压力发生变化时可以测到相应的压力值,Android设备通过USB对设备进行供电并与该设备进行通讯,将测量到的数据读取下来并进行保存分析。这是一个典型的Android设备作为USBHost、外接设备作为USBDevice的Host Mode。关于Android所提供的USB连接模式,可以参考:http://developer.android.com/guide/topics/connectivity/usb/index.html,这里对两种连接模式都做了比较详细的介绍,不再赘述。下面主要针对我所遇到的问题做一些分析。
首先看Host mode所需要用的的类:
UsbManager:Allows you to enumerate and communicate with connected USB devices.字面含义就是允许你列举并与已连接的USB设备进行交互,其实就是一个USB管理器,可以通过它来获取已连接的USB Device列表。使用上很简单:UsbManager manager = (UsbManager) getSystemService(USB_SERVICE);就可以获取到一个实例。
USBDevice:Represents a connected USB device and contains methods to access its identifying information, interfaces, and endpoints.表示一个已连接的USB设备,包含获取它的识别信息、接口和端点的方法。获取一个USBDevice列表的方法:HashMap
UsbInterface:Represents an interface of a USB device, which defines a set of functionality for the device. A device can have one or more interfaces on which to communicate on.表示一个为该设备定义了一个函数集的USB设备接口。一个设备可以拥有一个或多个用来交互的接口。获取一个设备的接口数量:int interfaceCount = device.getInterfaceCount();,如果使用index为0的interface则可以:UsbInterface ui = device.getInterface(0); 。
UsbEndpoint:Represents an interface endpoint, which is a communication channel for this interface. An interface can have one or more endpoints, and usually has input and output endpoints for two-way communication with the device. 表示一个接口端点,该端点作为这个接口的一个交互channel,一个接口可以拥有一个或多个端点,通常有输入和输出端点为一个设备提供两种交互方式。
UsbDeviceConnection:Represents a connection to the device, which transfers data on endpoints. This class allows you to send data back and forth sychronously or asynchronously.表示在通过端点与设备传输数据的一个连接,该类允许你同步或异步的发送信息出去或者回来。
在获取一个UsbEndpoint时,务必要执行conn.claimInterface(UsbInterface intf, boolean force)方法。在使用中
if(!um.hasPermission(device)){//判断是否拥有该设备的连接权限,如果没有则请求权限
um.requestPermission(device, this.createPendingResult(0, null, 0));
}
if(manager.hasPermission(device)){//如果已经拥有该设备的连接权限
conn = manager.openDevice(device);//打开一个UsbDeviceConnection
}
if(conn==null){
Toast.makeText(this, "USB设备连接不可用!", Toast.LENGTH_SHORT).show();
return false;
}
if(conn.claimInterface(ui, true)){//This must be done before sending or receiving data on any UsbEndpoints belonging to the interface.
point = ui.getEndpoint(1);
dataPoint = ui.getEndpoint(0);
return true;
}
如果配置正确的话,通过上面的几个类,应该可以成功的获得了一个可用的UsbEndpoint。
但需要注意的是,这时需要声明USB设备的信息,
<?xml version="1.0" encoding="utf-8"?>
具体的这些id需要根据所连接的设备而有所不同,这个资源文件必须声明在res/xml/device_filter.xml中
完成这个声明以后,一般的,在USB设备接入时,系统如果检测到该设备,如果此时需要提示则应该
...
...> ...
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
表示,在device_filter文件中的声明的设备连接到Android设备时,会触发连接的提示。
如果上面的连接正常,那么就可以与设备进行数据的传输了。
一般地,都会启动一个线程来完成这项工作。
request.initialize(conn, dataPoint);//初始化请求
ByteBuffer bb =ByteBuffer.allocate(2);//数据接收的ByteBuffer,具体大小要根据不同的设备而有所不同
while(canStop){
request.queue(bb, 2);
byte[] dst = new byte[2];
int accessRes = conn.bulkTransfer(point, access, 2, 1000);//发送USB外设所能执行的命令
if(accessRes<0){
return;
}
if(request == conn.requestWait()){//请求完成,如果发生错误则方法返回null
dst = bb.array();//返回的数据
}
}
UsbRequest:Represents an asynchronous request to communicate with a device through aUsbDeviceConnection.表示通过一个UsbDeviceConnection实例与设备进行交互的一个异步请求。
在这个数据传输的过程中,需要发送命令和接收数据,发送命令的方法有两个:
controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
Performs a control transaction on endpoint zero for this device. 参数requestType,该事务的请求类型,参数request,该事务的请求ID,参数value,该事务的值,参数index,该事务的索引,参数buffer,该事务的数据buffer,如果没有数据需要被发送或接收,可以为null,参数length,发送或接收数据的长度,参数timeout,超时时间,单位毫秒 另外一个是,bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
Performs a bulk transaction on the given endpoint. 参数endpoint,需要通过哪个端点来发送数据,参数buffer,要发送或接收的数据buffer,参数length,要发送或接收的数据长度,参数timeout,超时时间,单位毫秒 如果返回值为负值,则说明失败,否则返回发送成功数据的长度。 在发送完毕后,应当使用UsbDeviceConnection的requestWait()方法来等待响应获取返回的数据。 至此,整个连接设备与数据交互的过程就可以算完成了,具体到发送什么样的命令,根据所连接设备的不同自然也是不同的,整个流程大致就如上面所说。Google也提供了一个Demo,如果没有下载的话可以在 这里下载
更多相关文章
- 如何检索Android设备的唯一ID
- Android主流三方库源码分析(一、深入理解OKHttp源码)
- ubuntu linux通过adb命令行"复制粘贴"内容到android
- WebView之js调用Android类的方法传递数据 - 依凡王子
- Android设备的唯一ID
- Android设备到底侵犯了微软的什么专利
- Frida官方手册 - 在Android上使用Frida
- 简单聊一下Android音频通路的切换
- Android(安卓)数据存储与读取:SQLite