Как разблокировать InputStream.read () на Android?

У меня есть поток, в котором метод read() InputStream вызывается в цикле. Когда больше нет байтов для чтения, поток блокируется до тех пор, пока не появятся новые данные.

Если я вызову close() в InputStream из другого потока, поток закрывается, но заблокированный вызов read() прежнему остается заблокированным. Я бы предположил, что метод read() теперь должен возвращаться со значением -1 чтобы указать конец потока, но это не так. Вместо этого он остается заблокированным еще на несколько минут, пока не произойдет тайм-аут tcp.

Как разблокировать вызов close() ?

Редактировать:

По-видимому, регулярная JRE будет сразу бросать SocketException когда поток или сокет, соответствующий вызову blocking read() соответствует close() 'd. Тем не менее, я использую Java-среду для Android Java, но не буду.

Любые намеки на решение для среды Android были бы весьма признательны.

Вызывайте только read() когда имеются данные.

Сделайте что-нибудь подобное:

  while( flagBlock ) { if( stream.available() > 0 ) { stream.read( byteArray ); } } 

Установите flagBlock чтобы остановить чтение.

Когда другой конец закрывает соединение, ваш поток будет возвращать -1 на read (). Если вы не можете запустить другой конец, чтобы закрыть соединение, например, закрыв выходной поток, вы можете закрыть сокет, который вызовет исключение IOEx в потоке reading () блокировки.


Можете ли вы привести краткий пример, который воспроизводит вашу проблему?

 ServerSocket ss = new ServerSocket(0); final Socket client = new Socket("localhost", ss.getLocalPort()); Socket server = ss.accept(); Thread t = new Thread(new Runnable() { public void run() { int ch; try { while ((ch = client.getInputStream().read()) != -1) System.out.println(ch); } catch (SocketException se) { System.out.println(se); } catch (IOException e) { e.printStackTrace(); } } }); t.start(); server.getOutputStream().write("hi\n".getBytes()); Thread.sleep(100); client.close(); t.join(); server.close(); ss.close(); 

печать

 104 105 10 java.net.SocketException: Socket closed 

См. Java Concurrency In Practice для действительно хорошей системы для отмены потока при работе с сокетами. Он использует специальный исполнитель ( CancellingExecutor ) и специальный Callable ( SocketUsingTask ).

У нас была одна и та же проблема: исключение при переключении сети (например, переход от 3G к Wi-Fi при загрузке).

Мы используем код http://www.androidsnippets.com/download-an-http-file-to-sdcard-with-progress-notification , который отлично работает, за исключением случаев, когда сетевое соединение было потеряно.

В решении было указано значение тайм-аута, это стандартное значение 0 (что означает: бесконечно ждать).

  HttpURLConnection c = (HttpURLConnection) u.openConnection(); c.setRequestMethod("GET"); c.setDoOutput(true); c.setReadTimeout(1000); c.connect(); 

Поэкспериментируйте со значением тайм-аута, подходящим для вас.

Вы можете использовать пакет java.nio . NIO означает Non-blocking IO. Здесь вызовы (чтобы читать и писать) не блокируются. Таким образом, вы можете закрыть поток.

Здесь есть пример программы, которую вы можете посмотреть здесь . Метод: processRead

У меня была такая проблема на Samsung 2.3. При переключении с блоков 3G на Wifi InputStream.read (). Я пробовал все советы из этой темы. Ничего не помогло. С моей точки зрения это специфическая проблема устройства, потому что она должна вызывать IOException из-за javadoc . Мое решение состоит в том, чтобы прослушивать андроид-трансляцию android.net.conn.CONNECTIVITY_CHANGE и закрыть соединение из другого потока, это вызовет IOException в заблокированном потоке.

Вот пример кода:

DownloadThread.java

 private volatile boolean canceled; private volatile InputStream in; private boolean downloadFile(final File file, final URL url, long totalSize) { OutputStream out = null; try { Log.v(Common.TAG, "DownloadThread: downloading to " + file); in = (InputStream) url.getContent(); out = new FileOutputStream(file); return copy(out, totalSize); } catch (Exception e) { Log.e(Common.TAG, "DownloadThread: Exception while downloading. Returning false ", e); return false; } finally { closeStream(in); closeStream(out); } } public void cancelDownloading() { Log.e(Common.TAG, "DownloadThread: cancelDownloading "); canceled = true; closeStream(in); //on my device this is the only way to unblock thread } private boolean copy(final OutputStream out, long totalSize) throws IOException { final int BUFFER_LENGTH = 1024; final byte[] buffer = new byte[BUFFER_LENGTH]; long totalRead = 0; int progress = 0; int read; while (!canceled && (read = in.read(buffer)) != -1) { out.write(buffer, 0, read); totalRead += read; } return !canceled; }