Sonntag, April 5, 2020

Java.io.IOException, „bad file number“ USB-Verbindung

Ich bin einrichten eines USB-Zubehör die Verbindung zwischen meinem Android-Telefon und einem anderen Gerät. Nur das senden und bytes hin-und-her jetzt zu testen. Ich bekomme einige eindeutige Kommunikation geht auf den ersten, aber es endet immer sterben, mit Java.io.IOException: write failed: EBADF (Bad file number)" nach einer Sekunde oder so. Manchmal ist das Lesen am Leben bleibt, aber die Schrift stirbt; die anderen beiden sterben.

Ich mache nichts super schickes, Lesen und schreiben genau wie die Google-Dokumentation:

Ersten Verbindung (innerhalb des broadcast-receiver, ich weiß, das Teil funktioniert zumindest anfänglich):

if (action.equals(ACTION_USB_PERMISSION))
{
    ParcelFileDescriptor pfd = manager.openAccessory(accessory);
    if (pfd != null) {
        FileDescriptor fd = pfd.getFileDescriptor();
        mIn = new FileInputStream(fd);
        mOut = new FileOutputStream(fd);
    }
}

Lesen:

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        byte[] buf = new byte[BUF_SIZE];
        while (true)
        {
            try {
                int recvd = mIn.read(buf);
                if (recvd > 0) {
                    byte[] b = new byte[recvd];
                    System.arraycopy(buf, 0, b, 0, recvd);
                    //Parse message
                }
            }
            catch (IOException e) {
                Log.e("read error", "failed to read from stream");
                e.printStackTrace();
            }
        }
    }
});
thread.start();

Schreiben:

synchronized(mWriteLock) {
    if (mOut !=null && byteArray.length>0) {
        try {
            //mOut.flush();
            mOut.write(byteArray, 0, byteArray.length);
        }
        catch (IOException e) {
            Log.e("error", "error writing");
            e.printStackTrace();
            return false;
        }
    }
    else {
        Log.e(TAG, "Can't send data, serial stream is null");
        return false;
    }
}

Error-stacktrace:

java.io.IOException: write failed: EBADF (Bad file number)
W/System.err(14028):     at libcore.io.IoBridge.write(IoBridge.java:452)
W/System.err(14028):     at java.io.FileOutputStream.write(FileOutputStream.java:187)
W/System.err(14028):     at com.my.android.transport.MyUSBService$5.send(MyUSBService.java:468)
W/System.err(14028):     at com.my.android.transport.MyUSBService$3.onReceive(MyUSBService.java:164)
W/System.err(14028):     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:781)
W/System.err(14028):     at android.os.Handler.handleCallback(Handler.java:608)
W/System.err(14028):     at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err(14028):     at android.os.Looper.loop(Looper.java:156)
W/System.err(14028):     at android.app.ActivityThread.main(ActivityThread.java:5045)
W/System.err(14028):     at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err(14028):     at java.lang.reflect.Method.invoke(Method.java:511)
W/System.err(14028):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
W/System.err(14028):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
W/System.err(14028):     at dalvik.system.NativeStart.main(Native Method)
W/System.err(14028): Caused by: libcore.io.ErrnoException: write failed: EBADF (Bad file number)
W/System.err(14028):     at libcore.io.Posix.writeBytes(Native Method)
W/System.err(14028):     at libcore.io.Posix.write(Posix.java:178)
W/System.err(14028):     at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
W/System.err(14028):     at libcore.io.IoBridge.write(IoBridge.java:447)
W/System.err(14028):     ... 13 more

Habe ich die Protokollierung alle über dem Platz und ich somit weiß, dass es nicht etwas zu offensichtlich, wie eine andere Erlaubnis-Anfrage empfangen wird (und damit der Datei-streams wird neu initialisiert Mitte Lesen). Die streams nicht schließen, denn ich habe mir nie passieren, dass irgendwo in meinem code (für jetzt). Ich bin nicht immer alle freistehend oder befestigt Ereignisse entweder (ich log, dass, wenn es passiert). Es scheint nichts außergewöhnliches, es ist einfach stirbt.

Ich dachte, vielleicht war es ein concurrency-Problem, also spielte ich mit Schlösser und schläft, nichts funktionierte, dass ich es versucht habe. Ich glaube nicht, dass es ein Durchsatz Problem, entweder, weil es immer noch passiert, wenn ich schlafe jeder Lesen (an beiden enden), und Lesen Sie ein einziges packet at a time (super slow bitrate). Gibt es eine chance, dass der Puffer ist überrollt, und am anderen Ende irgendwie? Wie würde ich mich über die Aufklärung dieser? Ich habe Zugriff auf das andere Ende code, es ist ein Android-Gerät als auch mit Host-Modus. Im Falle, dass es darauf ankommt, kann ich post, dass der code zu – standard-bulk-transfers.

Funktioniert das Telefon nur haben glanzlose Unterstützung für Android-Accessory-Modus? Ich habe versucht, zwei Handys und beide scheitern gleichermaßen, so bezweifle ich, es ist, dass.

Frage ich mich, was diesen Fehler verursacht im Allgemeinen beim schreiben oder Lesen von USB auf Android?

  • Welche Android-version verwenden Sie? Auch, was sind Sie versuchen zu kommunizieren, mit? Ich glaube, dass mit Zubehör-Modus (verwenden Sie Android-Open-Accessory-Modus?) Sie benötigen ein host-Gerät kompatibel ist, wie die arduino-oder FT311D.
  • Android 4.0.4. Ich kann die erste Verbindung einwandfrei, und es gibt keine solche Sache wie ein „kompatibles“ Gerät – wenn Sie senden Sie die richtige Steuerung-Anfragen, das Telefon geht im Zubehör-Modus, wenn es unterstützt. Ein dialog erscheint auf meinem Handy, die besagt, dass es sieht ein Zubehör – nur Probleme mit dem halten der Verbindung.
  • Oh, ok, warten Sie, es sieht ein Accessoire, was bedeutet, Ihr Telefon ist im host-Modus dann nicht, Zubehör-Modus richtig? Welches Gerät ist die Bereitstellung der Strom -, Telefon-zu-Gerät oder Einrichtung, die auf das Telefon?
  • Nein, die Android-Dokumentation ist tatsächlich ein wenig verwirrend, mit der Terminologie. Es sieht ein Accessoire, das heißt, es geht in den Zubehör-Modus. Wenn Sie im Zubehör-Modus auf einem Handy, können Sie Durchlaufen UsbAccessory Objekte – Sie werden sehen, wie Sie im Zubehör-Modus. Das Gerät ist eine Art, wie ein Android-tablet (auch 4.0.4 glaube ich); es ist die Bereitstellung von Strom auf meinem Handy. Es ist die Kommunikation über Host-Modus. Dies alle funktioniert zunächst nur diese „bad file number“, kommt schließlich.
  • Ok, ich habe mit Open Accessory Modus meist so dass ich versuche nur, um herauszufinden, mehr Einzelheiten zu sehen, wie viel ich mag in der Lage sein, um Ihnen zu helfen… Also es klingt wie Sie haben zwei android-Geräten reden, über USB zwischen einander, ein host, ein Accessoire? Ist das richtig? Und Sie sind immer die „bad file number“ auf die Zubehör-android-Gerät?
  • Das ist richtig. Das Host-Gerät nicht erscheinen zu sein irgendwelche Probleme.

InformationsquelleAutor | 2013-04-12

3 Kommentare

  1. 8

    Ich habe dasselbe problem in meinem code, und ich fand, dass es geschieht, weil Filedescriptors Objekt wurde GCed.

    Ich das Problem gelöst, durch hinzufügen ParcelFileDescriptor Feld in Aktivität(oder Service).

    Ich habe Ihre ersten code-snippet und den code, den Sie basierend auf, und letztere hat ParcelFileDescriptor Feld im Thread.

    Ich denke, wenn Sie bei der Bearbeitung der code wie unten, es funktioniert gut.

    ParcelFileDescriptor mPfd;
    ...
    
    if (action.equals(ACTION_USB_PERMISSION))
    {
        mPfd = manager.openAccessory(accessory);
        if (mPfd != null) {
            FileDescriptor fd = mPfd.getFileDescriptor();
            mIn = new FileInputStream(fd);
            mOut = new FileOutputStream(fd);
        }
    } 
    • Vielen Dank für Ihren Beitrag zu diesem. Ich habe nicht mehr gemacht Jahre jetzt, aber hoffentlich werden die Leute es hilfreich finden.
    • Diese Antwort auf jeden Fall verdient mehr upvotes, die Tatsache ParcelFileDescriptor ist GC ‚ ed ist nicht offensichtlich, an alle, ich hatte eine Methode der Rückkehr new FileOutputStream(mPfd.getFileDescriptor()) und wollte nur sehen, Fehler wie, dass nach paar transfers. Ich verbrachte viele Stunden auf diesem, vielen Dank, Kumpel!
  2. 7

    Am Ende war es ein threading-Problem. Ich brauchte mehr richtig trennen, auch schriftlich, als auch, statt nur zu Lesen.

    Landete ich mit dieser code als Grundlage.

    • Hi, ich habe das gleiche Problem und ich habe gesehen, oben Links, aber nicht für mich gearbeitet. bitte teilen, was das threading-Problem.
  3. 1

    OK, ein paar Dinge, die ich bemerkte, das schien einfach anders aus, was ich für Open Accessory Modus, wodurch ich folgte die Dokumentation für USB-Zubehör meist, so ist es sollte sehr ähnlich sein, ist, dass Ihr mIn.read(buf); sollte mIn.read(buf, 0, 64); soweit ich weiß.

    Außerdem sollten Sie deklarieren Sie in Ihrer Klasse Erklärungen thread myThread;. Dann in Ihrem BroadcastReceiver nach dem erstellen der neuen FileInput/OutputStream haben myThread = new thread(myHandler, myInputStream); folgte meinem myThread.start();.

    Nun bemerkte ich, dass Sie kommunizieren direkt mit der Benutzeroberfläche von deinem thread. Sie sollten einen handler statt, dass der thread mitteilen und dann wird wieder die Kommunikation in Ihrer Benutzeroberfläche, zumindest von dem, was ich gelesen hatte.

    Hier ein Beispiel von meinem handler und thread:

    final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg){
    
        }
    };
    
    private class USB_Thread extends Thread {
        Handler thisHandler;
        FileInputStream thisInputStream;
    
        USB_Thread(Handler handler, FileInputStream instream){
            thisHandler = handler;
            thisInputStream = instream;
        }
        @Override
        public void run(){
            while(true) {
                try{
                    if((thisInputStream != null) && (dataReceived == false)) {
                        Message msg = thisHandler.obtainMessage();
                        int bytesRead = thisInputStream.read(USB_Data_In, 0, 63);
                        if (bytesRead > 0){
                            dataReceived = true;
                            thisHandler.sendMessage(msg);
                        }
                    }
                }
                catch(IOException e){
    
                }
            }
        }
    }

    Außerdem gibt es einige demo-open accessory application hier. Sie können helfen, mit Ihrem Verständnis von Zubehör-Modus.

    Und auch gibt es bekannte Probleme mit einer Anwendung, die nicht dem Erhalt der BroadcastReceiver für ACTION_USB_ACCESSORY/DEVICE_ATTACHED programmgesteuert. Es wird nur erhalten Sie über die manifest-Datei. Finden Sie mehr auf dieser hier und hier.

    Ich eigentlich nicht testen, setzen die dataReceived variable in der Prozedur, und erst vor kurzem geändert, dass ein Teil von meinem code. Habe es getestet und es hat nicht funktioniert, so versuchen sich zu erinnern, was es war, dass ich gelesen hatte, ich glaube, es war nicht über Variablen, die die Kommunikation innerhalb des threads, sondern versuchen, etwas zu verwenden, wie .setText(). Ich habe aktualisiert mein code, der dataReceived=true im thread. Die Prozedur würde dann verwendet werden, für die Aktualisierung von Elementen auf der Benutzeroberfläche, wie TextViews, etc.

    Thread

    FileDescriptor fd = mFileDescriptor.getFileDescriptor();
    mInputStream = new FileInputStream(fd);
    mOutputStream = new FileOutputStream(fd);
    usbThread = new USB_Thread(mHandler, mInputStream);
    usbThread.start();
    • Danke für die Tipps, aber ich bin nicht der direkten Kommunikation mit dem UI; wo hast du das denn her? Die mRead überlastung war ein guter Rat, ich sollte immer angeben, eine maximale, aber es hat nicht am Ende verändern Sie viel. Ich denke, dies kann ein hardware-Seite Thema….so schwer zu sagen.
    • Ja, die UI war ein falsch gelesen. Es könnte ein hardware-Problem zu. Ich habe getestet, Open Accessory-code auf drei verschiedene Tabletten, ein off-Marke, eine, die funktionierte überhaupt nicht, die Nexus-7, die gut funktioniert, außer beim Hochfahren aus dem ausgeschalteten Zustand und dann ein Galaxy Tab 2 7″, die funktioniert wie das Nexus aber nicht das Startproblem. Obwohl, wo sind Sie beginnen, Ihr thread Lesen?
    • Ich habe versucht, es an mehreren stellen; gerade jetzt in onCreate.
    • Ich editierte meine Antwort. Versuchen Sie etwas wie das für den thread direkt nach dem input – /output-stream-Erklärung. Vielleicht arbeiten…
    • Eine andere Sache, die mir gerade aufgefallen ist, versuchen Sie, den synchronized() Befehl vor Ihren ParcelFileDescriptor in Ihrem BroadcastReceiver.
    • Nochmal vielen Dank für die Tipps, ich habe versucht, einige Ihrer Vorschläge sowie andere Dinge, aber immer noch nicht. Aber ich grub weiter und das einzige, was ich sehen kann sieht der Ort ist ein StrictMode$InstanceCountViolation, die anscheinend deaktivieren Sie den strikten Modus. Versucht, kein Glück entweder. Ich werde versuchen, Sie explizit zu deklarieren Berechtigungen für das Telefon ich bin mit der in der hardware und sehen, ob das hilft Dingen.
    • Du bist herzlich willkommen. Und Sie haben das USB-Genehmigung erklärt in Ihrem manifest schon, richtig?

Kostenlose Online-Tests