Error al leer datos de InputStream en Bluetooth en Android

Estoy trabajando en una aplicación de Android, que utiliza la conexión Bluetooth para transferir datos entre mi smartphone android y un módulo bluetooth no android, utilizando el perfil SPP. He utilizado el ejemplo de chat de Bluetooth del sitio de desarrolladores de Android como referencia.

He logrado que dos dispositivos se conecten entre sí y envíen cadenas simples desde el teléfono inteligente al módulo bluetooth. Pero tengo un error al leer los datos enviados del módulo. He utilizado el siguiente código, que es exactamente el mismo que en Bluetooth Chat Ejemplo, para leer los datos de InputStream

while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); String str = new String(buffer); Log.i(TAG, "mmInStream - " + str); // Send the obtained bytes to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "disconnected", e); connectionLost(); break; } } 

Cuando mi módulo bluetooth envía una cadena simple al teléfono, esa cadena no se recibe correctamente. Se divide en varias piezas de manera aleatoria. Por ejemplo, si envío "1234567890abcdef1234567890abcdef0123456789" por tres veces al teléfono, Logcat en Eclipse registrará estos:

 mmInstream - 12345678910abcdef        (continuing null) mmInstream - 1        (continuing null) mmInstream - 2345678910abcdef0123456789        (continuing null) 

por primera vez. En la segunda y la tercera vez se transmiten datos, se reciben en una diferencia de piezas:

 mmInstream - 1234567891       (continuing null) mmInstream - 0abcdef012       (continuing null) mmInstream - 3456789         (continuing null) mmInstream - 1234567891                (continuing null) mmInstream - 0abcdef0123456789            (continuing null) 

No sé por qué sucede esto y cómo resolver este problema. Si los datos se reciben de una manera arbitraria como esta, no puedo obtener los datos necesarios para procesar. ¿Cómo puedo conseguirlo en una sola pieza?

Cualquier ayuda sería apreciada.

Muchas gracias.

8 Solutions collect form web for “Error al leer datos de InputStream en Bluetooth en Android”

Dos cosas que noté con tu código:

  • En primer lugar, enviar más abajo a su aplicación una referencia a la memoria intermedia en la que lee no siempre es una buena solución: ¿Qué pasa si entretanto el buffer se anula? Consulte este error en stackoverflow por ejemplo Puede evitarlo haciendo una copia de los datos (por ejemplo, use buffer.clone ()) que ha leído desde Bluetooth, o si no le gusta usar demasiada memoria puede hacer que su Leer un búfer circular.

  • Debe ser capaz de recompilar sus datos incluso si se reciben en paquetes separados (pero los paquetes se reciben en un período de tiempo corto). Por ejemplo, puede crear indicadores de inicio / parada. Ofc que todavía depende del tipo de objeto que envíe a través de Bluetooth …

Y ahora una posible solución si las 2 advertencias anteriores no sirven de nada es esto:

En lugar de un bucle infinito que llama .read – una llamada de bloqueo – puede hacer algo como esto:

 while(true) { if mmInStream.getAvailable()>0 { -your read code here- } else SystemClock.sleep(100); } 

Es un hack y todavía puede leer algunas partes del mensaje, ¡pero será muy raro!

¡Voto de Pls arriba / correcto si es útil!

Tengo un este problema y he resuelto el problema de este personajes de esta manera

 public void run() { int bytes; // bytes returned from read() int availableBytes = 0; // Keep listening to the InputStream until an exception occurs while (needRun) { try { availableBytes = mmInStream.available(); if(availableBytes > 0){ byte[] buffer = new byte[availableBytes]; // buffer store for the stream // Read from the InputStream bytes = mmInStream.read(buffer); Log.d("mmInStream.read(buffer);", new String(buffer)); if( bytes > 0 ){ // Send the obtained bytes to the UI activity mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget(); } } } catch (IOException e) { Log.d("Error reading", e.getMessage()); e.printStackTrace(); break; } } } 

¡El arreglo de Radu funciona fantástico !. Yo mismo he estado trabajando en este tema desde hace bastante tiempo usando el código de ejemplo de Bluetooth Chat. A continuación se muestra lo que estoy usando para capturar y mostrar la lectura de la temperatura desde un sensor remoto:

  // Keep listening to the InputStream while connected while (true) { try { byte[] buffer = new byte[128]; String readMessage; int bytes; if (mmInStream.available()>2) { try { // Read from the InputStream bytes = mmInStream.read(buffer); readMessage = new String(buffer, 0, bytes); }catch (IOException e) { Log.e(TAG, "disconnected", e); break; } // Send the obtained bytes to the UI Activity mHandler.obtainMessage(HomeBlueRemote.MESSAGE_READ, bytes, -1, readMessage) .sendToTarget(); } else { SystemClock.sleep(100); } } catch (IOException e) { e.printStackTrace(); } } } 

Como vemos, he modificado el (buffer.available ()> 0) a> 2. Esto se debe a que mi microcontrolador está enviando 2 bytes para la temperatura. . Antes de esta corrección, inputtream para el conteo de bytes variaría, a veces sólo capturaba 1 byte lo que desordenó la lectura de la pantalla de temperatura en la aplicación de Android. Una vez más, fuera de todas las sugerencias en la web, Radu tiene la mejor solución para el error android inputstream.

¡Lo encontré!

Debe restablecer el búfer:

 buffer = new byte [1024]; 

antes de esto:

 bytes = mmInStream.read(buffer); 

Por lo menos funcionó para mí, y no se necesita ningún comando de sueño.

Creo que hay muchas buenas respuestas. Mi contribución es procesar cada dígito uno a la vez a medida que entra en el flujo de entrada de Bluetooth de la siguiente manera. El valor de esto es asegurar que cada conjunto de datos es un valor de longitud (como una cadena), que se puede procesar muy fácilmente poniendo cada nuevo valor (contenido en la cadena readMessage en el controlador de actividad principal) en una lista. De esta manera, puede utilizar el objeto List (String) (el editor no me permitirá usar el objeto <>) para procesar los datos de nuevo en números reales extrayendo via

Integer.valueOf (List (String) objeto pasado aquí)

// Sigue escuchando el InputStream mientras está conectado mientras (true) {

  try { byte[] buffer = new byte[1]; // make this one byte to pass one digit at a time through Bluetooth Handler String readMessage; int bytes; if (mmInStream.available()>2) { try { // Read from the InputStream bytes = mmInStream.read(buffer); readMessage = new String(buffer, 0, bytes); }catch (IOException e) { Log.e(TAG, "disconnected", e); break; } // Send the obtained bytes to the UI Activity mHandler.obtainMessage(HomeBlueRemote.MESSAGE_READ, bytes, -1, readMessage) .sendToTarget(); } 

He utilizado los dos últimos códigos, que funcionan bien, aunque cuando la conexión se pierde la interfaz de usuario no se notifica y por lo que el estado no cambia a STATE_NONE. En mi caso quiero que la aplicación intente volver a conectar el último dispositivo siempre que se pierda la conexión. Después de intentar muchas maneras finalmente solucioné el problema de esta manera:

  1. He creado un carácter END, este personaje que sé que nunca utilizaré, pero sólo en el final de la cadena que estoy enviando. "." Es mi final de carácter de cadena.
  2. He creado una cadena temporal tmp_msg.
  3. Cada vez que se recibe un Stream, se crea un segundo String temporal "readMessage" de ese Stream.
  4. "ReadMessage" se busca el carácter final (".").
  5. Si no se detecta el carácter final, "readMessage" se concatinated a tmp_msg. Así que cuando el carácter final no se recibe primero y segundo y tercero tmp_msg = readMessage1 + readMessage2 + readMessage3.
  6. Cuando final carácter "." Se detecta, tmp_msg se concatinated con el último readMessage y los bytes "buffer" se construyen fuera de él.
  7. "Buffer" entonces se envía a la interfaz de usuario, y tmp_msg se reinicializa a "" (cadena vacía). Aquí está el código completo: (no se debe hacer ninguna modificación con la actividad de BluetoothChat).

     public void run() { Log.i(TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; // Keep listening to the InputStream while connected String tmp_msg =""; while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); String readMessage = new String(buffer, 0,bytes); if (readMessage.contains(".")){ tmp_msg+=readMessage; byte[] buffer1 = tmp_msg.getBytes(); int bytes1=buffer1.length; tmp_msg=""; // Send the obtained bytes to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_READ,bytes1,-1,buffer1).sendToTarget(); }else{ tmp_msg+=readMessage; } } catch (IOException e) { // Log.e(TAG, "disconnected", e); connectionLost(); // Start the service over to restart listening mode BluetoothChatService.this.start(); break; } } } 

Prueba esto:

 public void run() { byte[] buffer; ArrayList<Integer> arr_byte = new ArrayList<Integer>(); while (true) { try { int data = mmInStream.read(); if(mmInStream.available()>0) { arr_byte.add(data); } else { arr_byte.add(data); buffer = new byte[arr_byte.size()]; for(int i = 0 ; i < arr_byte.size() ; i++) { buffer[i] = arr_byte.get(i).byteValue(); } Log.e("INPUT",new String(buffer)); mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); arr_byte = new ArrayList<Integer>(); } } catch (IOException e) { break; } } } 

También tuve este problema. Ahora está funcionando bien. Sin Personajes.

Mi manera: Construyo un textView en MainActivity con su id siendo txtReceive.

 @Override public void run() { byte[] buffer=new byte[1024]; int bytes; while(true) { try { bytes = inputStream.read(buffer); final String strReceived = new String(buffer, 0, bytes); runOnUiThread(new Runnable() { @Override public void run() { txtReceive.append(strReceived); } }); } catch (Exception e) { Log.d(TAG, "loi "); runOnUiThread(new Runnable() { @Override public void run() { txtReceive.setText("Error"); } }); } } } 
  • Abrir la pantalla de configuración para activar el método de entrada
  • Thread para capturar un tiempo de espera de InputStream.read () BluetoothSocket
  • Múltiples comandos a través de Jsch Shell
  • Leer / dev / input / event en android a través del lenguaje de programación Java
  • ¿Cómo puedo diseñar una etiqueta HTML INPUT para que mantenga CSS cuando se centre en Android 2.2+?
  • La entrada en los resultados de autocompletar de jQuery se activa al seleccionar del resultado
  • Teclado amigable de correo electrónico de Android en el campo de entrada de webview
  • Habilitar teclado de correo electrónico en android para el tipo de entrada de correo electrónico
  • ¿Hay alguna manera de desactivar la función de zoom en los campos de entrada en la vista web?
  • Diálogo de texto de entrada de Android
  • ¿Cómo puedo detectar la entrada táctil en Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.