I am using Galaxy Nexus (4.2.2) and ADK Board(PIC24F of Microchip Co.) to make an application using Android Open Accessory.

After the following events happen while communicating USB, if it launches my app again, OutputStream.write() throws an IOException(ENODEV) whenever it tries to transmit data to ADK Board.

・App was forcibly killed by Android OS (e.g. Memory shortage, task killer app, etc.)
・App was updated with new version.

It comes to succeed after USB detached once.

code:

    public void openAccessory(UsbAccessory accessory) {

        ParcelFileDescriptor p = mUsbManager.openAccessory(accessory);
        if (p == null) { return;} 
        else {mFileDescriptor = p;}

        FileDescriptor fd = mFileDescriptor.getFileDescriptor();
        if (fd == null) {return;}

        mOutputStream = new FileOutputStream(fd);
        if (isSendSuccess()) {
            mInputStream = new FileInputStream(fd);
        }
    }


    private boolean isSendSuccess() {
        final byte[] test = new byte[]{0x01,02};

        for (int i=0; i<2; i++) { //send test
            try {
                mOutputStream.write(test);
                return true;
            } catch (IOException e) {
                e.printStackTrace(); //throw ENODEV after app is forced kill.
            }
        }
        return false;
    }


error log:

    W/System.err(17198): java.io.IOException: write failed: ENODEV (No such device)
    W/System.err(17198):    at libcore.io.IoBridge.write(IoBridge.java:462)
    W/System.err(17198):    at java.io.FileOutputStream.write(FileOutputStream.java:187)
    ・・・・・・
    W/System.err(17198): Caused by: libcore.io.ErrnoException: write failed: ENODEV (No such device)
    W/System.err(17198):    at libcore.io.Posix.writeBytes(Native Method)
    W/System.err(17198):    at libcore.io.Posix.write(Posix.java:178)
    W/System.err(17198):    at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
    W/System.err(17198):    at libcore.io.IoBridge.write(IoBridge.java:457)
    W/System.err(17198):    ... 23 more

codicil:
I know that there is an existing problem, such as:
http://code.google.com/p/android/issues/detail?id=20545

So, I regularly send data from ADK Board to my app, and it works fine.
However, the above problem occurs.

Could you advise if there is a workaround ?
Thanks.

有帮助吗?

解决方案

This is a known bug in UsbManager, for several years already: Issue 20545: Unable to cleanly close USB accessory FileInputStream

A fix developed but haven't merged into Android trunk yet: Issue 61390: Potential source code fixes for UsbAccessory not unbinding cleanly

Also you may want to look at this discussion: Proper way to close a USB accessory connection to workaround ideas in some use cases.

I'm working with a customized Android ROM (CyanogenMod) so I'll probably try to apply the fix from 61390. I did a lot of testing trying to workaround it myself, but I was not able to get a stable solution. I was considering to use libusb port instead: https://github.com/OpenNI/OpenNI2/tree/master/ThirdParty/PSCommon/XnLib/ThirdParty/libusb-1.0.9-Android (from https://stackoverflow.com/a/16234205/1028256, you can upvote it there), it is told to work even on not rooted phones (I haven't tried myself), and it supports async mode, so one can avoid blocking thread in Java. But you will have to use JNI, still it's much better than any non-stable solution IMHO.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top