上一篇介绍了读取Android手机连接的USB设备信息的例子,本篇介绍官方文档中关于USB的API:官方API。注:主要介绍关于Host Mode的。
1)UsbAccessory
用于代表USB从设备的一个类,这个从设备通过USB数据线与Android应用进行通信。
2)UsbConfiguration
用于代表USB设备(指连接Android手机的USB从设备)配置信息的一个类。
3)UsbConstants
这个类主要包含USB协议常量的类,这些常量与Linux内核下linux/usb/ch9.h 里面定义的相对应。
4)UsbDevice
这个类代表在Host Mode下,连接Android手机的USB设备的类。
equals(object) : 用于判断本设备是否与object相等,在编程时判断两个设备是否为同一设备时会用到。
其余的get函数都是返回相应的值。如:getDeviceProtocol()返回代表协议的常量,getDeviceProtocol()==UsbConstants.USB_CLASS_HID则说明此设备为HID设备。
getInterfaceCount():返回设备的接口总数。对于U盘的接口数为1。
getInterface():获取接口(UsbInterface)。
5)UsbInterface
这个类代表USB设备上的一个接口。一个USB设备可以有1个或多个接口,每个接口提供不同的功能。一个接口又有1个或者多个端点(UsbEndpoint),端点是用于数据或者命令传输的通道。
getEndpointCount():返回此接口的端点数。对于U盘,返回的端点数为2(用上一篇博客介绍的方法可得)。
getEndpoint(index):返回对应的端点。
6)UsbEndpoint
这个类代表接口上的一个端点。端点是用于数据传输的通道。典型的bulk端点用于传输大量的数据,interrupt端点用于传输小量数据,如事件,与数据流分开传输。在官方文档中说端点0是用于传输控制信息的,而端点0是所有USB设备都默认拥有的。但是这个端点0并不会被枚举出来,也就是说,要传输control信息直接用controlTransfer()传输即可,不要试图打开端点0后再进行传输。举个例子:大家所熟悉的U盾,为HID设备,拥有一个接口,缺省的控制端点;用getInterface(0)获取接口0,在getEndpointCount()返回的值为0,端点数为0;控制端点没有被枚举出来。再如U盘有一个接口,拥有控制端点,bulk-in端点,bulk-out端点,总共3个,但是getEndpointCount()返回的值是2。还有鼠标键盘等HID设备为单向传输设备,不能被获取到。
注:在Google API中提到的endpoint 0特指控制端点,而不是指端点号为0的端点。
7)UsbManager
这个类允许你获取USB的状态并和USB设备进行通信。
openDevice(),打开要进行通信的USB设备,返回一个UsbDeviceConnection对象。
在使用UsbDeviceConnection对象进行通信前,必须获取权限(获取使用者的同意)。使用
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
获取UsbManager对象,用hasPremission()判断设备是否拥有权限,如果没有,使用如下方法获取权限
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
mUsbManager.requestPermission(mUsbDevice, mPermissionIntent);
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
// 获取权限后的操作
}
else {
finish();
}
}
}
}
};
8)UsbRequest
一个代表请求传输数据包的类。UsbRequest类可以用于在bulk端点和interrupt端点传输数据。control信息的传输不可使用此类。
9)UsbDeviceConnection
这个类用于在Android手机从USB设备接收和发送控制信息和数据信息。此类由openDevice()创建。
bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
这个函数用于数据传输的。
endpoint 为传输端点,注意端点的方向。
buffer 为传输的数据,至于传输数据的格式,需要了解手中的设备具体PDF,不然发送的数据是无意义的,并且无法接收数据。
length 为buffer的长度。
timeout 为有效时间(设为0可能导致程序意外终止退出)。
返回值传输的数据的长度,小于0说明传输失败。
controlTransfer (int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
这个函数用于控制信息的传输,后面三个参数与上面相同。requestType 为请求类型,低8位为有效的,第7为表示方向如0x00为发送数据,0x80为接收数据,接收数据时,buffer要有足够的长度。其余7位的设置根据手中设备提供的文档进行设置。(具体值都会在设备文档中给出)
request 与上面的request对应。(具体值都会在设备文档中给出)
value 与上面两个参数对应。(具体值都会在设备文档中给出)
index 表示使用的接口号。(具体值都会在设备文档中给出)
HID设备文档下载地址:HID设备文档
U盘设备文档下载地址:U盘bulk-only传输文档
(1)建立连接(HID设备)
private void makeConnection() {
if(mUsbDevice == null) {
Toast.makeText(this, R.string.no_device, Toast.LENGTH_SHORT).show();
finish();
return;
}
if(mUsbDevice.getInterfaceCount() != 1) {
Toast.makeText(this, R.string.interface_error, Toast.LENGTH_SHORT).show();
finish();
return;
}
UsbInterface intf = mUsbDevice.getInterface(0);
if (mUsbDevice != null) {
UsbDeviceConnection connection = mUsbManager.openDevice(mUsbDevice);
if (connection != null && connection.claimInterface(intf, true)) {
Toast.makeText(this, R.string.connection_fine, Toast.LENGTH_SHORT).show();
mConnection = connection;
} else {
Toast.makeText(this, R.string.connection_error, Toast.LENGTH_SHORT).show();
mConnection = null;
finish();
}
}
}
(2)发送控制信息(mCmd[8]请根据自己的设备进行设置)
private void sendCommand() {
synchronized (this) {
if (mConnection != null) {
mCmd = new byte[8];
mCmd[0] = (byte) 0x00; //请自行设置
mCmd[1] = (byte) 0x00;
mCmd[2] = (byte) 0x00;
mCmd[3] = (byte) 0x00;
mCmd[4] = (byte) 0x00;
mCmd[5] = (byte) 0x00;
mCmd[6] = (byte) 0x00;
mCmd[7] = (byte) 0x00;
int result = mConnection.controlTransfer(0x21, 0x09, 0x0300, 0x00, mCmd, mCmd.length, 1000);
if(result < 0) {
Toast.makeText(this, R.string.send_command_failed, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, R.string.send_command_successed, Toast.LENGTH_SHORT).show();
}
}
}
}
(3)根据发送的控制信息,接收控制信息的结果(HID设备)
private void recvMessage() {
synchronized (this) {
if (mConnection != null) {
byte[] message = new byte[32];
int result = mConnection.controlTransfer(0xA1, 0x01, 0x0300, 0x00, message, message.length, 1000);
if(result < 0) {
Toast.makeText(this, R.string.recv_message_failed, Toast.LENGTH_SHORT).show();
mMessageView.setText(R.string.string_null);
} else {
Toast.makeText(this, R.string.recv_message_successed, Toast.LENGTH_SHORT).show();
String str = new String();
for(int i=0; i<message.length; i++) {
str += Integer.toHexString(message[i]&0x00FF) + " ";
}
mMessageView.setText(str);
}
}
}
}
上面是我U盾操作中截取的,请原谅我不能公开命令参数!
Android USB Host的API的简要介绍就到这里,不明白的请看下一篇:Android bulk-only U盘操作实例