11

そこで、Linuxを実行しているラップトップに電話を接続して電話をUSBアクセサリモードにすることができるように、Android USBAccessoryAPIを実装しました。次に、アクセサリにアクセスして開き、書き込みを開始します。私のコードは、ドキュメントの例とほとんど同じに見えます。主な違いは、私が別々の読み取りメソッドと書き込みメソッドを使用しており、ネイティブコードからJNIを介してそれらにアクセスしていることです。

ここが面白いところです。1〜2秒間正常に読み取り/書き込みを行った後、ラップトップからの一括転送書き込みでタイムアウトエラーが発生し始め、AndroidのUSBアクセサリへの読み取り呼び出しでENODEVエラーコードを含むIOExceptionがスローされます。これはケーブルが接続されたままであり、UsbManagerはまだリストにアクセサリをリストしており、私はまだそれに対する許可を持っています。

奇妙なことに、読み取りループで100ミリ秒のスリープを設定すると、問題は基本的に解消されることを発見しました(ただし、それでも時々発生します)。そこに眠っているのはひどい恨みであるだけでなく、私のアプリに耐えられないほどの待ち時間をもたらします。スリープ時間が短いほど、ハッキングの効果は低くなり、10ミリ秒のスリープ時間では効果がなくなります。

バルク転送を使用して約20〜30kbpsのリアルタイムデータを送信しています(ただし、バルク転送では不十分なほどリアルタイムではありません)。転送サイズは約20〜30Hzで50〜800バイトの範囲です。USBの制限でしょうか?あまり経験がないので、基本的にはネットワークソケットと同じように扱っています。小さいメッセージをキューに入れて、頻度は少ないが大きい転送で一緒に送信する必要がありますか?小さくて高頻度のバルク転送に問題はありますか?これを調べてみますが、基本的にはここでストローを握っています。

ハードウェア:

  • ラップトップはUbuntu10.04を実行しており、libusb1.0.0を使用しています。
  • 電話はGalaxyNexusSを実行しているストックAndroid4.1.2です。
4

1 に答える 1

6

そのため、進行中のすべてをまだ理解していませんが、ダブルバッファリングスキームを実装すると問題が解決しました。

フルスピードで読み取るJavaAndroidアプリにはENODEVの問題がないことを発見しました。これにより、JavaNativeInterfaceが問題の原因であるという結論に至りました。

以前は、ポーリング方式でJNIから呼び出されたメソッドから直接UsbAccessoryから読み取っていました。ネイティブコードからJavaへの移行、そしてJavaからネイティブAndroidカーネルへの移行についての何かが、明らかにすべてを不機嫌にしました。

私の修正は、Javaのみのスレッド(JNI呼び出しなし)からUsbAccessoryに読み取り/書き込みを行い、そのデータをバッファリングして、JNIによって呼び出されるメソッドから読み取り/書き込みを行うことでした。

魅力のように機能するようです。以前は、アクセサリ側で非常に一貫して送信タイムアウトが発生し、最終的には上記のようにAndroid側でIOExeceptionが発生しましたが、現在はタイムアウトもIOExceptionも発生していません。何がその動作を正確に引き起こしているのかはまだ少し気になりますが、理解するには強力なJNIカンフーが必要だと思います。

于 2012-11-07T07:12:08.617 に答える