安卓USB主机通讯
Posted
技术标签:
【中文标题】安卓USB主机通讯【英文标题】:Android USB Host Communication 【发布时间】:2012-02-16 01:42:37 【问题描述】:我正在开发一个利用 android 3.2 中的 USB 主机功能的项目。一般来说,我在 USB/串行通信方面缺乏知识和人才,这令人遗憾。我也找不到我需要做的任何好的示例代码。
我需要从 USB 通信设备读取数据。 例如:当我通过 Putty 连接(在我的 PC 上)时,我输入:
>GO
设备开始为我输出数据。俯仰/滚动/温度/校验和。
例如:
$R1.217P-0.986T26.3*60
$R1.217P-0.986T26.3*60
$R1.217P-0.987T26.3*61
$R1.217P-0.986T26.3*60
$R1.217P-0.985T26.3*63
我可以从 Android 设备发送初始的“GO”命令,此时我会收到“GO”的回显。
然后在任何后续读取中都没有其他内容。
我该怎么做: 1) 发送“go”命令。 2) 读入产生的数据流。
我正在使用的 USB 设备具有以下接口(端点)。
设备类:通信设备(0x2)
接口:
接口 #0 类:通信设备(0x2) 端点 #0 方向:入站 (0x80) 类型:中断(0x3) 轮询间隔:255 最大数据包大小:32 属性:000000011
接口 #1 类:通信设备类 (CDC) (0xa) 端点 #0 地址:129 1号 方向:入站 (0x80) 类型:散装(0x2) 轮询间隔 (0) 最大数据包大小:32 属性:000000010
端点 #1 地址2 2号 方向:出站 (0x0) 类型:散装(0x2) 轮询间隔 (0) 最大数据包大小:32 属性:000000010
我能够处理权限、连接到设备、找到正确的接口并分配端点。我只是无法确定使用哪种技术发送初始命令来读取随后的数据。我尝试了 bulkTransfer 和 controlTransfer 的不同组合,但没有成功。
谢谢。
我正在使用接口#1,如下所示:
public AcmDevice(UsbDeviceConnection usbDeviceConnection, UsbInterface usbInterface)
Preconditions.checkState(usbDeviceConnection.claimInterface(usbInterface, true));
this.usbDeviceConnection = usbDeviceConnection;
UsbEndpoint epOut = null;
UsbEndpoint epIn = null;
// look for our bulk endpoints
for (int i = 0; i < usbInterface.getEndpointCount(); i++)
UsbEndpoint ep = usbInterface.getEndpoint(i);
Log.d(TAG, "EP " + i + ": " + ep.getType());
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
if (ep.getDirection() == UsbConstants.USB_DIR_OUT)
epOut = ep;
else if (ep.getDirection() == UsbConstants.USB_DIR_IN)
epIn = ep;
if (epOut == null || epIn == null)
throw new IllegalArgumentException("Not all endpoints found.");
AcmReader acmReader = new AcmReader(usbDeviceConnection, epIn);
AcmWriter acmWriter = new AcmWriter(usbDeviceConnection, epOut);
reader = new BufferedReader(acmReader);
writer = new BufferedWriter(acmWriter);
【问题讨论】:
对于我们这些苦苦挣扎的人来说,您是如何选择接口 1 的,接口 0(中断接口)用于什么目的?谢谢! 【参考方案1】:我不想回答我自己的问题,但是……我明白了。我只是混淆了我的阅读和写作。此外,该设备不喜欢我在命令末尾使用的 '\n'。它似乎与 '\r' 相处得更好。
我最终使用 android 的 bulkTransfer 进行读写。我的文字是这样的。
try
device.getWriter().write(command + "\r");
device.getWriter().flush();
catch (IOException e)
throw new RuntimeException(e);
还有我的 BufferedWriter 的重写写入方法:
@Override
public void write(char[] buf, int offset, int count) throws IOException
byte[] buffer = new String(buf, offset, count).getBytes(Charset.forName("US-ASCII"));
int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
读数相似:
char[] buffer = new char[BUF_SIZE];
try
BufferedReader reader = device.getReader();
int readBytes = reader.read(buffer);
Log.d(TAG, "BYTES READ: " + readBytes);
catch (IOException e)
throw new RuntimeException(e);
String strBuf = new String(buffer).trim();
if (DEBUG)
Log.d(TAG, "Read: " + strBuf);
还有:
@Override
public int read(char[] buf, int offset, int count) throws IOException
byte[] buffer = new byte[count];
int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
if (byteCount < 0)
throw new IOException();
char[] charBuffer = new String(buffer, Charset.forName("US-ASCII")).toCharArray();
System.arraycopy(charBuffer, 0, buf, offset, byteCount);
return byteCount;
这一切都是在这样一个线程中开始的:
new Thread()
@Override
public void run()
String command = "go";
write(command);
while (true)
String coords = read();
.start();
很明显,这只是 comm 的东西,我现在需要对它做点什么(把它放在一个可以使用处理程序向*** UI Activity 报告的服务中)。但这部分已经弄清楚了。
非常感谢从事 rosjava 工作的人们 (http://code.google.com/p/rosjava/)...他们已经完成了很多很棒的项目,他们的代码非常有帮助。
添加我的设备类以帮助澄清问题。
import com.google.common.base.Preconditions;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
/* This class represents a USB device that supports the adb protocol. */
public class BKDevice
// private static final int TIMEOUT = 3000;
private final UsbDeviceConnection usbDeviceConnection;
private final BufferedReader reader;
private final BufferedWriter writer;
public static final String TAG = "AcmDevice";
public BKDevice(UsbDeviceConnection usbDeviceConnection,
UsbInterface usbInterface)
Preconditions.checkState(usbDeviceConnection.claimInterface(
usbInterface, true));
this.usbDeviceConnection = usbDeviceConnection;
UsbEndpoint epOut = null;
UsbEndpoint epIn = null;
// look for our bulk endpoints
for (int i = 0; i < usbInterface.getEndpointCount(); i++)
UsbEndpoint ep = usbInterface.getEndpoint(i);
Log.d(TAG, "EP " + i + ": " + ep.getType());
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
if (ep.getDirection() == UsbConstants.USB_DIR_OUT)
epOut = ep;
else if (ep.getDirection() == UsbConstants.USB_DIR_IN)
epIn = ep;
if (epOut == null || epIn == null)
throw new IllegalArgumentException("Not all endpoints found.");
BKReader acmReader = new BKReader(usbDeviceConnection, epIn);
BKWriter acmWriter = new BKWriter(usbDeviceConnection, epOut);
reader = new BufferedReader(acmReader);
writer = new BufferedWriter(acmWriter);
public BufferedReader getReader()
return reader;
public BufferedWriter getWriter()
return writer;
添加 BKReader 代码:
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.util.Log;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
public class BKReader extends Reader
private static final int TIMEOUT = 1000;
private final UsbDeviceConnection connection;
private final UsbEndpoint endpoint;
public BKReader(UsbDeviceConnection connection, UsbEndpoint endpoint)
this.connection = connection;
this.endpoint = endpoint;
@Override
public int read(char[] buf, int offset, int count) throws IOException
byte[] buffer = new byte[count];
int byteCount = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
if (byteCount < 0)
throw new IOException();
char[] charBuffer = new String(buffer, Charset.forName("US-ASCII")).toCharArray();
System.arraycopy(charBuffer, 0, buf, offset, byteCount);
return byteCount;
@Override
public void close() throws IOException
【讨论】:
你是如何得到 device.getwriter() 的? flush() 方法会做什么? 我的设备类包含一个 BufferedWriter。 getWriter 返回该对象。因此,flush() 只是刷新流。为了提供帮助,我将在上面粘贴我的课程代码。 什么是 BKReader ?好像是你写的一门课。你也可以显示一些代码吗? @P_Rein,我在原始解决方案的末尾添加了 BK Reader 代码。 @K.R.您是否有以编程方式将 android 文件复制到 USB 驱动器的经验?以上是关于安卓USB主机通讯的主要内容,如果未能解决你的问题,请参考以下文章