2013-04-12 5 views
11

मैं अपने एंड्रॉइड फोन और किसी अन्य डिवाइस के बीच एक यूएसबी एक्सेसरी कनेक्शन स्थापित कर रहा हूं। परीक्षण के लिए अभी बस बाइट भेजना। मुझे पहले कुछ निश्चित संचार मिल रहा है, लेकिन यह एक या दूसरे के बाद Java.io.IOException: write failed: EBADF (Bad file number)" के साथ हमेशा मर जाता है। कभी-कभी पढ़ना जिंदा रहता है लेकिन लेखन मर जाता है; अन्य दोनों मर जाते हैं।Java.io.IOException, "खराब फ़ाइल संख्या" यूएसबी कनेक्शन

मैं कुछ भी सुपर फैंसी नहीं कर रहा हूँ, पढ़ना और सिर्फ गूगल प्रलेखन की तरह लेखन:

प्रारंभिक कनेक्शन (एक प्रसारण रिसीवर के अंदर, मैं जानता हूँ कि इस हिस्से कम से कम शुरू काम करता है):

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

पढ़ना:

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

लेखन:

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

त्रुटि स्टैकट्रेस: ​​

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 

मैं हर जगह प्रवेश करने की है और इस तरह मैं जानता हूँ कि यह इस तरह एक और अनुमति अनुरोध प्राप्त की जा रही (और इस प्रकार फ़ाइल धाराओं के मध्य पढ़ इसे पुनः शुरू किया जा रहा) के रूप में कुछ भी भी स्पष्ट नहीं है । धाराएं या तो बंद नहीं हो रही हैं, क्योंकि मेरे पास कभी भी मेरे कोड में कहीं भी ऐसा नहीं होता है (अभी के लिए)। मुझे कोई अलग या संलग्न घटनाएं नहीं मिल रही हैं (मैं लॉग इन करता हूं अगर ऐसा होता है)। साधारण से कुछ भी नहीं लगता है; यह बस मर जाता है।

मैंने सोचा कि शायद यह एक सहमति मुद्दा था, इसलिए मैंने ताले के साथ खेला और सोया, मैंने कोशिश की कि कुछ भी नहीं किया। मुझे नहीं लगता कि यह एक थ्रूपुट मुद्दा है क्योंकि यह तब भी होता है जब मैं हर पठन (दोनों सिरों पर) सोता हूं, और एक समय में एक सिंगल पैकेट पढ़ता हूं (सुपर धीमी बिटरेट)। क्या किसी मौके पर बफर को दूसरे छोर पर ओवरराउन किया जा रहा है? मैं इसे साफ़ करने के बारे में कैसे जाउंगा? मेरे पास दूसरे सिरे के कोड तक पहुंच है, यह होस्ट मोड का उपयोग करके एक एंड्रॉइड डिवाइस भी है। यदि यह महत्वपूर्ण है, तो मैं उस कोड को भी पोस्ट कर सकता हूं - मानक थोक हस्तांतरण।

क्या फ़ोन के पास एंड्रॉइड एक्सेसरी मोड के लिए कम समर्थन है? मैंने दो फोनों की कोशिश की है और वे दोनों समान रूप से असफल हो जाते हैं, इसलिए मुझे संदेह है कि यह है।

मुझे आश्चर्य है कि एंड्रॉइड पर यूएसबी से लिखते या पढ़ने के दौरान सामान्य रूप से यह त्रुटि क्या होती है?

+0

एंड्रॉइड का कौन सा संस्करण आप उपयोग कर रहे हैं? इसके अलावा, आप किसके साथ संवाद करने की कोशिश कर रहे हैं? मेरा मानना ​​है कि एक्सेसरी मोड के साथ (क्या आप एंड्रॉइड ओपन एक्सेसरी मोड का उपयोग कर रहे हैं?) आपको एक मेजबान डिवाइस की आवश्यकता है जो arduino या FT311D जैसा संगत है। – TronicZomB

+0

एंड्रॉइड 4.0.4। मैं प्रारंभिक कनेक्शन को ठीक कर सकता हूं, और "संगत" डिवाइस जैसी कोई चीज़ नहीं है - यदि आप सही नियंत्रण अनुरोध भेजते हैं, तो फ़ोन सहायक उपकरण में जाता है यदि यह इसका समर्थन करता है। एक संवाद मेरे फोन पर बताता है कि यह एक सहायक को देखता है - कनेक्शन को रखने में समस्याएं हैं। –

+0

ओह ठीक है, प्रतीक्षा करें कि यह एक सहायक को देखता है, जिसका अर्थ है कि आपका फोन होस्ट मोड में है, तो एक्सेसरी मोड सही नहीं है? कौन सा डिवाइस बिजली, फोन टू डिवाइस या डिवाइस को फोन प्रदान कर रहा है? – TronicZomB

उत्तर

7

यह एक सूत्रण मुद्दा जा रहा समाप्त हो गया। मुझे बस पढ़ने के बजाय, और भी लिखने के साथ-साथ लिखने की भी आवश्यकता है।

मैं आधार के रूप में this code का उपयोग कर समाप्त हुआ।

+1

हाय, मेरे पास एक ही समस्या है और मैंने लिंक के ऊपर देखा है लेकिन मेरे लिए काम नहीं किया है। कृपया थ्रेडिंग समस्या क्या साझा करें। – ashokk

1

ठीक है, कुछ चीजें मैंने देखा है कि मैं ओपन एक्सेसरी मोड के लिए जो कुछ करता हूं उससे अलग दिखता हूं, जिसे मैंने यूएसबी एक्सेसरी के लिए प्रलेखन का पालन किया था, इसलिए यह बहुत समान होना चाहिए, यह है कि आपका mIn.read(buf);mIn.read(buf, 0, 64); होना चाहिए जैसा की मैं जनता हूँ।

इसके अलावा, आपको अपनी कक्षा घोषणाओं thread myThread; में घोषित करना चाहिए। फिर के भीतर नया FileInput/OutputStream बनाने के बाद, myThread = new thread(myHandler, myInputStream); पर मेरे myThread.start(); का पालन करें।

अब मैंने देखा है कि आप सीधे अपने धागे से यूआई के साथ संचार कर रहे हैं। आपको एक हैंडलर का उपयोग करना चाहिए, इसके बजाय थ्रेड संवाद करेगा और फिर जो मैंने पढ़ा था उससे कम से कम आपके यूआई पर संवाद करेगा।

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

      } 
     } 
    } 
} 

इसके अलावा, वहाँ कुछ डेमो खुला गौण आवेदन here हैं:

यहाँ मेरी हैंडलर और धागे का एक उदाहरण है।वे सहायक मोड की आपकी समझ में मदद कर सकते हैं।

और प्रोग्राम के साथ ACTION_USB_ACCESSORY/DEVICE_ATTACHED के लिए ब्रॉडकास्ट रिसीवर प्राप्त करने वाले एप्लिकेशन के साथ ज्ञात समस्याएं भी हैं। यह केवल इसे प्रकट फ़ाइल के माध्यम से प्राप्त होगा। आप इस here और here पर और अधिक पा सकते हैं।

मैंने वास्तव में हैंडलर में dataReceived चर डालने का परीक्षण नहीं किया और हाल ही में मेरे कोड के उस हिस्से को बदल दिया। मैंने इसका परीक्षण किया और यह काम नहीं किया, इसलिए यह याद रखने की कोशिश कर रहा था कि मैंने क्या पढ़ा था, मुझे लगता है कि यह धागे के भीतर संचार करने वाले चर के बारे में नहीं था, लेकिन .setText() जैसे कुछ उपयोग करने की कोशिश कर रहा था। मैंने धागे में dataReceived=true को शामिल करने के लिए अपना कोड अपडेट किया है। हैंडलर तो, यूआई पर आइटम अद्यतन करने के लिए इस्तेमाल किया जाएगा जैसे TextView रों, आदि

थ्रेड

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

युक्तियों के लिए धन्यवाद, लेकिन मैं यूआई के साथ सीधे संचार नहीं कर रहा हूं; आपने यह कहां से प्राप्त किया था? 'MRead' अधिभार अच्छी सलाह थी, मुझे हमेशा अधिकतम निर्दिष्ट करना चाहिए, लेकिन यह बहुत अधिक नहीं बदलता है। मुझे लगता है कि यह एक हार्डवेयर पक्ष मुद्दा हो सकता है .... कहना मुश्किल है। –

+0

हाँ, यूआई एक गलतफहमी थी। यह भी एक संभावित हार्डवेयर मुद्दा हो सकता है।मैंने तीन अलग-अलग टैबलेट पर ओपन एक्सेसरी कोड का परीक्षण किया है, एक ऑफ ब्रैंड जिसने बिल्कुल काम नहीं किया है, नेक्सस 7 जो ऑफ स्टेट से बिजली उठाने के बाद अच्छी तरह से काम करता है और फिर गैलेक्सी टैब 2 7 "जो नेक्सस की तरह काम करता है लेकिन स्टार्टअप समस्या नहीं है। हालांकि आप अपना रीड थ्रेड कहां से शुरू कर रहे हैं? – TronicZomB

+0

मैंने इसे कई स्थानों पर आजमाया है; अभी 'ऑनक्रेट' में। –

7

मुझे अपने कोड में एक ही समस्या मिली, और मैंने पाया कि ऐसा इसलिए होता है क्योंकि फ़ाइलडिस्क्रिप्टर ऑब्जेक्ट जीसीड था।

मैंने गतिविधि (या सेवा) में पार्सलफ़ाइलडिस्क्रिप्टर फ़ील्ड जोड़कर इस समस्या को ठीक किया।

मैंने आपके पहले कोड स्निपेट और आपके द्वारा आधारित कोड की जांच की, और बाद में थ्रेड में पार्सलफ़ाइलडिस्क्रिप्टर फ़ील्ड है।

मुझे लगता है कि यदि आप नीचे अपना कोड संपादित करते हैं, तो यह अच्छी तरह से काम करता है।

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

इसमें योगदान करने के लिए धन्यवाद। मैंने पिछले कुछ वर्षों में ऐसा नहीं किया है, लेकिन उम्मीद है कि लोग इसे उपयोगी पाते हैं। –

+0

यह उत्तर निश्चित रूप से अधिक अपवर्तनीय हकदार है, तथ्य यह है कि ParcelFileDescriptor GC'ed बिल्कुल स्पष्ट नहीं है, मेरे पास नई फ़ाइलऑटपुटस्ट्रीम (mPfd.getFileDescriptor()) लौटने का एक तरीका था और कुछ स्थानांतरण के बाद उस तरह की त्रुटियां देख रही थीं। मैंने इस पर कई घंटे बिताए, धन्यवाद दोस्त! –

संबंधित मुद्दे