java android sockets inputstream android-4.2-jelly-bean

java - No se puede leer el socket InputStream en Jelly Bean



android sockets (7)

Amigo,

prueba inputStream.readLine(); (es decir) DataInputStream.readLine(); (Método obsoleto)

esto funcionó para mí ...

Tengo una conexión de socket TCP que funciona bien en Android 2.3 pero ahora enfrenta algunos problemas en Android 4.1. El problema es que el método InputStream.read () siempre devuelve -1 (sin bloqueo), al igual que la conexión está cerrada.

Creando un socket

SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("c.whatsapp.net", 5222); socket.setSoTimeout(3*60*1000); socket.setTcpNoDelay(true);

Recuperando flujos de entrada y salida y escribiendo algunos datos iniciales:

InputStream inputStream = new BufferedInputStream(socket.getInputStream()); OutputStream outputStream = new BufferedOutputStream(socket.getOutputStream()); outputStream.write(87); outputStream.write(65); outputStream.write(1); outputStream.write(2); outputStream.flush();

Entonces, esta condición siempre pasa sin bloquear:

int c = inputStream.read(); if (c < 0) { Log.d(TAG, "End of stream"); }

Este código se ejecuta en un hilo de fondo . Y estaba trabajando en Gingerbread.

Intenté usar InputStreamReader y OutputStreamWriter en lugar de transmisiones directas, sin efecto.



El uso de BufferedReader y PrintWriter funciona en todas las versiones para mí y es extremadamente conveniente para enviar y recibir todo lo que desee (incluso cadenas JSON) a través de cualquier protocolo de comunicación. Intente guardarlos como variables miembro al iniciar su hilo de fondo de esta manera:

mInput = new BufferedReader(new InputStreamReader( socket.getInputStream())); mOutput = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true);

Para la comunicación asincrónica, el hilo de fondo podría verse así:

@Override public final void run() { while (!Thread.currentThread().isInterrupted()) { if (mInput == null) { break; } String message = null; try { message = mInput.readLine(); } catch (IOException e) { // handle the exception as you like break; } if (Thread.currentThread().isInterrupted()) { // thread was interrupted while reading break; } else if (message != null) { // handle the message as you like } } }

Use otra cadena de fondo para enviar mensajes:

@Override public void run() { if (mOutput != null) { mOutput.println(<message to be ); if (mOutput == null) { // the above thread was interrupted while writing } else if (!mOutput.checkError()) { // everything went fine } else { // handle the exception } } }

Además, deberá cerrar las transmisiones desde el exterior para asegurarse de que readLine no bloquee para siempre:

try { mOutput.close(); mInput.close(); mOutput = null; mInput = null; } catch (IOException e) { // log the exception }

Ahora, dado que está utilizando sockets TCP, es posible que el socket esté realmente muerto y readLine siga bloqueando. Tienes que detectar eso y cerrar las transmisiones justo como arriba. Para eso, tendrá que agregar otro hilo (oh bien) que periódicamente envía mensajes keep-alive. Si no se recibió ningún mensaje del dispositivo remoto durante X segundos, debe cerrar las transmisiones.

Todo este enfoque asegura que el socket esté cerrado y que todos los hilos terminen en cualquier circunstancia. Por supuesto, puede hacer que la comunicación sea sincrónica, si eso es lo que necesita, eliminando el hilo emisor e incluyendo println () dentro del hilo lector. Espero que eso te ayude (aunque la respuesta llega 8 meses tarde).


He tenido un problema similar y lo solucioné con una solución como esta

private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); private static class WatchDog implements Runnable{ private Thread thread = Thread.currentThread(); public void run() { Log.d(LOG_TAG, "Interrupting read due to timeout"); thread.interrupt(); } } private void read(InputStream in, ByteBuffer bb, long waitTime) throws IOException { int startingPos = bb.position(); long timeout = System.currentTimeMillis() + RESPONSE_TIMEOUT; ScheduledFuture<?> watchdogFuture = executor.schedule(new WatchDog(), RESPONSE_TIMEOUT, TimeUnit.MILLISECONDS); try { while(System.currentTimeMillis() < timeout && bb.hasRemaining()){ //workaround fixing timeout after 1ms try{ int read = in.read(bb.array(), bb.position(), bb.remaining()); if(read > 0){ bb.position(bb.position()+read); } } catch(SocketTimeoutException e){} if(bb.hasRemaining()){ Thread.sleep(5); } } watchdogFuture.cancel(true); } catch (InterruptedException e) {} if(bb.hasRemaining()){ throw new SocketTimeoutException("Unable to read requested bytes: " + (bb.position()-startingPos) + "/" + (bb.limit()-startingPos) + " after " + (System.currentTimeMillis() - timeout + RESPONSE_TIMEOUT) + "ms"); } }


He visto ese mismo error antes, aunque esta respuesta podría parecer oftálmica dale una oportunidad y avísame si funcionó, por alguna razón las tomas tienen un comportamiento extraño en jellybean incluso cuando funcionaban completamente bien en las versiones inferiores de Android, La forma en que arreglé este problema fue mover el targetSdkVersion al jelly bean, así como el Project Build Target bajo las propiedades de Android del proyecto, no modificó una sola línea de código, solo eso, y por alguna razón hace el truco. .

Espero que esto ayude.

¡Saludos!


Prueba este código -

Runnable runnable = new Runnable() { @Override public void run() { synchronized (this) { Socket s = null; String inMsg = null, msg2 = null; try { try { s = new Socket(server, port); } catch (Exception e) { return; } BufferedReader in = new BufferedReader( new InputStreamReader(s.getInputStream())); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); try { inMsg = in.readLine() + System.getProperty("line.separator"); } catch (Exception e) { return; } out.write(message + "/n/r"); out.flush(); try { msg2 = in.readLine(); if (msg2 == null) { return; } } catch (Exception e) { return; } out.close(); s.close(); } catch (Exception e) { return; } } } };

Esto funciona para mi.


Tuve un problema similar cuando inputStream.read() devolvió -1 y no recibí ninguna excepción. De hecho, el servidor estaba caído y la conexión rota. No lo probé con diferentes versiones, solo con 4.0.

Aquí está el informe de errores de Google sobre este comportamiento.

Lamentablemente, el estado del error parece estar "cerrado" como no reproducible.

Mi trabajo fue interpretar el -1 como un cierre del socket y un servidor inalcanzable. Cuando intentas reconectarte, obtienes los errores correctos.