Java.io.IOException, «неправильный номер файла» USB-соединение

Я настраиваю USB-аксессуар между телефоном Android и другим устройством. Просто отправьте байты туда и обратно, чтобы проверить. Сначала я получаю определенное сообщение, но он всегда заканчивается тем, что умирает с помощью Java.io.IOException: write failed: EBADF (Bad file number)" через секунду или около того. Иногда чтение остается в живых, но письмо умирает; умереть.

Я не делаю ничего сверхъестественного, читаю и пишу, как в документации Google:

Первоначальное соединение (внутри широковещательного приемника, я знаю, что эта часть работает хотя бы изначально):

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

Ошибка 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 

Я регистрируюсь повсюду, и, таким образом, я знаю, что это не слишком очевидно, например, другой полученный запрос разрешения (и, таким образом, файловые потоки повторно инициализируются в середине чтения). Потоки также не закрываются, потому что я никогда не встречал этого в моем коде (пока). Я тоже не получаю никаких отдельных или присоединенных событий (я регистрирую это, если это произойдет). Ничто не кажется слишком необычным; Он просто умирает.

Я подумал, что это проблема параллелизма, поэтому я играл с замками и спит, ничего не работало, что я пытался. Я не думаю, что это проблема пропускной способности, потому что это все еще происходит, когда я сплю каждое чтение (на обоих концах) и читаю один пакет за раз (супер медленный биттрейт). Есть ли вероятность того, что буфер будет переполнен на другом конце каким-то образом? Как я могу это исправить? У меня есть доступ к коду другого конца, это также устройство Android, используя режим Host. В случае, если это имеет значение, я могу опубликовать и этот код – стандартные массовые переводы.

Есть ли у телефона просто тусклая поддержка Android-аксессуаров? Я пробовал два телефона, и они оба терпели неудачу, поэтому я сомневаюсь, что это так.

Мне интересно, что вызывает эту ошибку вообще при записи или чтении с USB на Android?

Solutions Collecting From Web of "Java.io.IOException, «неправильный номер файла» USB-соединение"

В конечном итоге это была проблема с потоками. Мне нужно было более точно изолировать даже письмо, а не просто читать.

В итоге я использовал этот код .

У меня такая же проблема в моем коде, и я обнаружил, что это происходит, потому что объект FileDescriptor был GCed.

Я исправил эту проблему, добавив поле ParcelFileDescriptor в Activity (или Service).

Я проверил ваш первый фрагмент кода и код, на котором вы основывались, и у последнего есть поле ParcelFileDescriptor в Thread.

Я думаю, что если вы отредактируете свой код, как показано ниже, он работает хорошо.

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

Хорошо, некоторые вещи, которые я заметил, просто казались отличными от того, что я делаю для Open Accessory Mode, и в основном я следил за документацией для USB-аксессуаров, так что это должно быть очень похоже, это ваш mIn.read(buf); Должен быть mIn.read(buf, 0, 64); насколько я знаю.

Кроме того, вы должны объявить в своем объявлении класс thread myThread; , Затем в вашем BroadcastReceiver после создания нового 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){ } } } } 

Кроме того, здесь есть приложение для демонстрации открытых аксессуаров. Они могут помочь вам в понимании вспомогательного режима.

А также есть известные проблемы с приложением, не получающим BroadcastReceiver для ACTION_USB_ACCESSORY/DEVICE_ATTACHED программно. Он получит его только через файл манифеста. Вы можете найти больше об этом здесь и здесь .

Я на самом деле не тестировал поместить переменную dataReceived в обработчик и только недавно изменил эту часть моего кода. Я тестировал его, и это не сработало, поэтому, пытаясь вспомнить, что я читал, я думаю, что речь .setText() не о переменных, связанных в потоках, а при попытке использовать что-то вроде .setText() . Я обновил свой код, чтобы включить dataReceived=true в поток. Затем обработчик будет использоваться для обновления элементов в пользовательском интерфейсе, таких как TextView и т. Д.

Нить

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