2012-02-10 23 views
7

Tengo una aplicación que usa el bluetooth para recibir algunos datos (bytes) de otro dispositivo. todo va bien, pero tengo un pequeño problema al recibir todos los bytes. Después de recibir los bytes, los muestro en un Toast solo para probarlos. Cuando el otro dispositivo envía 10 bytes juntos (por ejemplo: "ABCDEFGHIJ"), el programa tomará el primer byte "A" solamente y lo mostrará en un Toast, luego irá a la segunda iteración y leerá los otros 9 bytes y mostrará " BCDEFGHIJ "en la tostada. Aquí está mi código:¿Cómo se leen todos los bytes juntos a través de Bluetooth?

byte[] buffer = new byte[1024]; // Read 1K character at a time. 
int bytes = 0; // Number of bytes. 

while(true) 
{ 
    try 
    { 
     // Read from the InputStream. 
     bytes = bInStream.read(buffer); 

     // Send the obtained bytes to the MainActivity. 
     mainActivityHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); 
    } 
    catch(IOException e) 
    { 
     connectionLost(); 
     break; 
    } 
} 

En el MainActivity, que tengo:

// The Handler that gets information back from the BluetoothManager. 
private final Handler handler = new Handler() 
{ 
    @Override 
    public void handleMessage(Message msg) 
    { 
     switch(msg.what) 
     { 
      case MESSAGE_READ: 
       byte[] readBuf = (byte[]) msg.obj; 

       // construct a string from the valid bytes in the buffer. 
       String readMessage = new String(readBuf, 0, msg.arg1); 
       Toast.makeText(MainActivity.this, readMessage, Toast.LENGTH_SHORT).show(); 
       break; 

      // ... 
     } 
    } 
}; 

¿Cómo puedo recibir todos los bytes juntos ?!

+0

¿Puedo ver cómo se va a enviar sus mensajes? ¿Estás haciendo algo como bOutStream.write ("ABCDEFGHIJ" .getBytes()) o estás escribiendo caracteres uno a la vez? – broody

+0

Un módulo bluetooth está conectado a arduino, entonces estoy usando el monitor serie del software arduino para enviar el mensaje. –

Respuesta

6

Mmm muy probablemente el culpable sea la forma en que está enviando los mensajes. Su recepción no tiene problemas, recibirá tantos bytes (hasta 1024) como se escriben.

Si no tiene control sobre la forma en que se envían los mensajes, es probable que pueda leer un byte a la vez y luego enviar un mensaje de controlador cuando llegue a un terminador predefinido. Ejemplo: "ABCDEFGHIJ #" donde # es el terminador.

String msg = ""; 
byte ch; 
while((ch=mInStream.read())!='#') { 
    bytes++; 
    msg+=ch; 
} 
+0

+1 Buena solución. Usaré esta solución hasta que encuentre otra manera de solucionar el problema. ¡Gracias! –

+0

¿Qué sucede si transfiero datos binarios? ¿Cómo puedo estar seguro de que el terminador no es parte de la secuencia de datos? – stoefln

4

La conexión bluetooth se basa en la transmisión, no en paquetes. No hay garantía o intento de preservar la paquetización. Por lo tanto, cualquier cantidad de escrituras puede dar como resultado una cantidad de lecturas, solo se garantiza que la secuencia de bytes es correcta. Si necesita detectar paquetes, debe proporcionar su propia estructura de paquetes para envolver sus datos. Por ejemplo, agregue un campo de longitud antes de cada paquete de datos para que pueda reconstruir en el lado de recepción.

+0

+1 Esta es también una buena solución. ¡Gracias! –

+0

@TJD ¿Y cómo sé la longitud del campo de longitud? – stoefln

-1

Una manera de manejar los mensajes más largos de lo búfer (puede ser peligroso porque puede llevar hasta su memoria si no aclarado) es para manejarlos en trozos:

String inString = ""; 
byte[] buffer = new byte[1024]; // buffer store for the stream 
int bytes; // bytes returned from read() 

while (true) { 
    try { 
     bytes = mmInStream.read(buffer); 
     String chunk = new String(buffer, 0, bytes); 
     if(chunk.contains(";")) 
     { 
      inString += chunk.substring(0,chunk.indexOf(';')); 
      Message msg = new Message(); 
      msg.obj = inString; 
      handler.sendMessage(msg); 
      inString = chunk.substring(chunk.indexOf(';')); 
     } 
     else 
     { 
      inString += chunk; 
     } 
    } catch (IOException e) { 
     break; 
    } 
} 
+0

no me puede ayudar a leer todos los mensajes dentro del buffer –

+0

el código asume ';' es el delimitador del mensaje el código es una implementación de ejemplo, y no es universal; no puede copiarlo y pegarlo y espera trabajar sin modificaciones, pero muestra un concepto detrás.y lee todos los mensajes. una vez que se llega al final del mensaje, handler.sendMessage (msg); se llama para manejar el mensaje completo, y el procesamiento del búfer continúa. Debe implementar el controlador para procesar/leer los mensajes. ese es el concepto –

2

La respuesta aceptada de @broody es correcta . Pero si los datos en sí contienen '#', podría ser difícil obtener los datos. Entonces, el mejor enfoque según yo es agregar '\ n' seguido de '\ r' (o cualquier otro carácter que es poco probable que aparezca como datos Refer ASCII Table) en el dispositivo que envía datos a su aplicación de Android. Simplemente actúa como avance de línea y marca el final de los datos.

Ej: ABCDEFGH \ n \ r

A continuación, el código puede ser algo como esto:

byte[] buffer = new byte[1024]; 
while (true) { 

     // Read from the InputStream 
      buffer[bytes] = (byte) mmInStream.read();     
     // Send the obtained bytes to the UI Activity 
if ((buffer[bytes] == '\n')||(buffer[bytes]=='\r')) 
{ 
    mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); 
    bytes=0; 
} 
else 
bytes++; 
} 

creo que sirve Saludos

+0

** Brillante **! Eso resolvió mi problema, sin agregar el carácter '#' adicional en el lado de Arduino. Simplemente me salté el cheque por el '\ r' (solo compruebo' \ n'), y funciona como un amuleto. –

Cuestiones relacionadas