Intereting Posts
Избегайте передачи null в качестве корня представления (необходимо разрешить параметры макета на корневом элементе раздутого макета) Изображение пользователя android share from url Активность Android Refresh при возврате на него Что заставляет контент ContentResolver.query () Android возвращать null? Как удалить фокус из SearchView? Исключение в потоке «main» java.lang.NoClassDefFoundError: junit / textui / ResultPrinter Можно ли изменить ширину и высоту макета в Android во время выполнения? Android Храните пакетный объект в SQLite Android Как правильно утилизировать растровые изображения при использовании RecyclerView? Сделать полосу прокрутки видимой в ионном контенте при использовании естественного прокрутки Android: метод doInBackground Asynctask вызывается после длительной задержки Styles.xml inherit "? Android: attr / borderlessButtonStyle"? Как найти UUID устройства последовательного порта Bluetooth? Начало работы с Android SDK от WeChat Как остановить Eclipse от попыток запуска XML-файлов?

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