从Android USB附件读取会引发ENODEV IOException

时间:2012-10-31 15:29:00

标签: android usb libusb

所以我已经实现了Android USB附件API,这样我就可以将手机插入运行Linux的笔记本电脑,并将手机置于USB附件模式。然后我可以访问附件,打开它,然后开始阅读它。我的代码与the documentation中的示例几乎完全相同。主要区别在于我使用单独的读写方法并通过本机代码通过JNI访问它们。

这里有趣的地方。成功读取/写入一两秒后,我的笔记本电脑的批量传输写入开始发出超时错误,然后对Android中的USB附件的读取调用会引发带有ENODEV错误代码的IOException。这是在电缆仍然连接的情况下,UsbManager仍然列出了列表中的附件,我仍然有权使用它。

为了增加它的奇特性,我发现如果我在读取循环中放置一个100ms的睡眠,问题基本上消失了(虽然它偶尔会发生)。在那里睡觉不仅仅是一个可怕的kludge,但它在我的应用程序中引入了无法忍受的延迟。睡眠时间越短,黑客的有效性越低,在10ms的睡眠时间内无效。

我使用批量传输传输大约20-30kbps的实时数据(但不是那么实时,批量传输就足够了),传输大小范围从50到800字节在大约20-30Hz。这可能是USB的限制吗?我没有太多的经验,所以我基本上把它当作一个网络套接字处理它。我是否应该将较小的消息排队并以较低频率但较大的传输将它们一起发送出去?小型,高频率的批量转移是否存在问题?我会调查一下这个,但我基本上都在抓稻草。

设备:

  • 笔记本电脑正在运行Ubuntu 10.04并使用libusb 1.0.0。
  • 手机是Galaxy Nexus S正在运行的Android 4.1.2。

1 个答案:

答案 0 :(得分:6)

所以,虽然我仍然不了解正在发生的一切,但实施双缓冲方案解决了我的问题。

我发现Java Android App全速阅读并没有出现ENODEV问题,这让我得出结论,Java Native Interface是我问题的根源。

以前,我直接从JNI以轮询方式调用的方法从UsbAccessory中读取。关于从本机代码转换到Java然后从Java转换到本机Android内核的事情显然使得一切都变得脾气暴躁。

我的修复是从仅Java线程(没有JNI调用)读取/写入UsbAccessory,然后缓冲该数据以从JNI调用的方法读取/写入。

似乎像魅力一样工作。在我在附件端非常一致地发送超时之前,然后最终如上所述在Android端的IOExeception,现在我没有超时,没有IOExceptions。我仍然有点好奇究竟是什么导致了这种行为,但我怀疑它需要强大的JNI功夫才能理解。