2013-04-12 15 views
11

Android telefonumla başka bir cihaz arasında bir USB aksesuar bağlantısı kuruyorum. Şimdilik test etmek için sadece baytlar gönderiyorum. İlk başta kesin bir iletişim kuruyorum, ama her seferinde Java.io.IOException: write failed: EBADF (Bad file number)" ile ölüyor. Bazen okuma canlı kalır, ancak yazı ölür; diğerleri de ölür.Java.io.IOException, "hatalı dosya numarası" USB bağlantısı

Okumayı ve sadece Google belgelerine gibi yazma, süper fantezi hiçbir şey yapmıyorum:

İlk bağlantısı (bir yayın alıcı içinde, bu bölüm en azından başlangıçta çalıştığını biliyorum):

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); 
    } 
} 

Okuma:

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(); 

Yazma:

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; 
    } 
} 

Hata 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 

Tüyler her yere giriş ve böylece ben böyle başka izin isteği alınıyor (ve dolayısıyla dosya akışları orta okunan yeniden başlatıldı edilmektedir) gibi, çok bariz şey olmadığını biliyorum . Akarsular da kapanmıyor, çünkü hiçbir zaman benim kodumda hiçbir zaman bu olmadı (şimdilik). Ayrılmış ya da iliştirilmiş olaylar almıyorum (eğer böyle bir şey olursa olsun). Hiçbir şey sıradan değil gibi görünüyor; Sadece ölür.

Belki bir eşzamanlılık sorunu olduğunu düşündüm, bu yüzden kilitler ve uykularla oynadım, denediğim hiçbir şey işe yaramadı. Her ne kadar her okumada (her iki uçta) uyuduğumda ve bir seferde tek bir paket okuduğumda (süper yavaş bit hızı) hala geçerli olduğu için bir iş çıktısı sorun değil. Bir şekilde diğer tarafta tamponun taşması ihtimali var mı? Bunu temizlemek için nasıl giderim? Diğer ucun koduna erişimim var, bu da bir Android cihazı ve Host modunu kullanıyor. Önemli olduğu takdirde, bu kodu da - standart toplu transferler gönderebilirim.

Telefonda Android Aksesuar Modu için yeterli destek yok mu? İki telefonu denedim ve ikisi de benzer şekilde başarısız oluyor, bu yüzden bundan şüpheliyim.

Genel olarak Android'deki USB'den yazarken veya okurken bu hatanın neden kaynaklandığını merak ediyorum.

+0

Hangi Android sürümünü kullanıyorsunuz? Ayrıca, ne ile iletişim kurmaya çalışıyorsunuz? Aksesuar Modu ile (Android Açık Aksesuar Modunu mu kullanıyorsunuz?) Arduino ya da FT311D gibi uyumlu bir ana bilgisayara ihtiyacınız olduğuna inanıyorum. – TronicZomB

+0

Android 4.0.4. İlk bağlantıyı gayet iyi anlayabiliyorum ve "uyumlu" bir cihaz diye bir şey yok - doğru kontrol isteklerini gönderirseniz, telefon destekliyorsa telefon aksesuar modunda ilerler. Telefonumda bir aksesuar göründüğünü belirten bir iletişim kutusu açılıyor - sadece bağlantıyı sürdürmede sorun yaşıyorum. –

+0

Tamam, bekle bir aksesuar görüyor, yani telefonun ana modda olduğu anlamına geliyor, aksesuar modu değil mi? Telefonu hangi cihaza, güce, cihaza veya cihaza sağlayan cihaz sağlıyor? – TronicZomB

cevap

7

Bir iş parçacığı sorunu olmaktan sona erdi kullanılacaktır. Sadece okumak yerine, yazmayı bile daha doğru bir şekilde ayırmam gerekiyordu.

Temel olarak this code kullanarak bitti.

+1

Merhaba, Bende aynı sorun var ve yukarıdaki bağlantıyı gördüm ama benim için işe yaramadı. lütfen iş parçacığı sorununu paylaşın. – ashokk

1

Tamam, ben sadece ben çoğunlukla USB aksesuarına belgelerine izledi Açık Aksesuar Modu için yaptığından farklı görünüyordu, bu yüzden çok benzer olmalıdır fark birkaç şey senin mIn.read(buf); kadarıyla mIn.read(buf, 0, 64); olmasıdır bildiğim gibi. Ayrıca, thread myThread; sınıf bildirimlerinde de bildirmeniz gerekir. Ardından, FileInput/OutputStream'u oluşturduktan sonra BroadcastReceiver içinde myThread = new thread(myHandler, myInputStream); ürünümü myThread.start(); izledim.

Şimdi UI ile doğrudan iş parçacığından iletişim kurduğunuzu fark ettim. İşleyiciyi, iş parçacığının iletişim kuracağı ve daha sonra, okuduklarımdan en azından UI'nize ileteceği bir işleyici kullanmalısınız.

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){ 

      } 
     } 
    } 
} 

Ayrıca, bazı demo açık aksesuar uygulama here vardır: İşte

benim işleyici ve iplik bir örnektir.Aksesuar modunu anlamanıza yardımcı olabilirler. Ayrıca, ACTION_USB_ACCESSORY/DEVICE_ATTACHED için BroadcastReceiver'ı program aracılığıyla almayan bir uygulama ile ilgili bilinen sorunlar vardır. Sadece manifest dosyası aracılığıyla alınacaktır. Bu here ve here üzerinde daha fazlasını bulabilirsiniz.

Aslında işleyicide dataReceived değişkenini koymayı test etmedim ve kodumun yalnızca bir kısmını değiştirdim. Onu test ettim ve işe yaramadı, bu yüzden ne okuduğumu hatırlamaya çalıştım, sanırım bu konudaki iletişim değişkenleri hakkında değil, .setText() gibi bir şeyi kullanmaya çalışıyorum. Kodumu dataReceived=true iş parçacığına eklemek için güncelleştirdim. işleyici sonra, UI öğeleri güncellemek için gibi TextView s, vb

Konu

FileDescriptor fd = mFileDescriptor.getFileDescriptor(); 
mInputStream = new FileInputStream(fd); 
mOutputStream = new FileOutputStream(fd); 
usbThread = new USB_Thread(mHandler, mInputStream); 
usbThread.start(); 
+0

İpuçları için teşekkürler, ancak doğrudan kullanıcı arayüzü ile iletişim kurmuyorum; Bunu nereden aldın? MRead'in aşırı yüklenmesi iyi bir öneriydi, her zaman bir maksimum belirtmeliydim, ama çok fazla değişmedi. Bunun bir donanım tarafı sorunu olabileceğini düşünüyorum .... söylemek zor. –

+0

Yea, UI yanlış yazılmıştı. Olası bir donanım sorunu da olabilir.Açık Aksesuar kodunu üç farklı tablette test ettim, hiç çalışmayan bir marka, Nexus 7, kapalı bir durumdan güç alan ve daha sonra Nexus gibi çalışan bir Galaxy Tab 2 7 "dışında çalıştı ama başlangıç ​​sorunum yok.Ama okumak için ne zaman başlıyorsun? – TronicZomB

+0

Birden fazla yerde denedim, şu anda 'onCreate'. –

7

Kodumda aynı sorunla karşılaştım ve bunun, FileDescriptor nesnesinin GCed olduğu için olduğunu anladım.

Bu sorunu, Faaliyet (veya Hizmet) bölümünde ParcelFileDescriptor alanını ekleyerek düzelttim.

İlk kod snippet'inizi ve temel aldığınız kodu kontrol ettim ve ikincisi de Thread'de ParcelFileDescriptor alanı var.

Aşağıdaki gibi kodunuzu düzenlerseniz iyi çalışır.

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); 
    } 
} 
+1

Buna katkıda bulunduğunuz için teşekkür ederiz. Bunu yıllardır yapmadım ama umarım insanlar yardımcı olur. –

+0

Bu cevap kesinlikle daha fazla vermeyi hak ediyor, ParcelFileDescriptor GC'ed'in hiç de açık olmadığını, yeni FileOutputStream (mPfd.getFileDescriptor()) döndüren bir yönteme sahiptim ve birkaç aktarımdan sonra böyle hataları görüyordum. Bu konuda çok zaman harcadım, teşekkürler dostum! –

İlgili konular