2013-06-11 7 views
5

Ho scaricato il campione Android di app di chat Bluetooth per inviare il testo tra due dispositivi Android tramite Bluetooth.Impossibile inviare dati di testo tra due dispositivi bluetooth in Android?

Ho installato ed eseguito questa app in due dispositivi Android.

ho affrontato molti problemi in quel codice

  1. scoperta Servizio fallito eccezione - fisso
  2. java.io.IOException: software ha causato l'interruzione della connessione - fisso
  3. java.io.IOException : Connessione ripristinata da Peer - Colpito su questo
.210

1. Azzerato la scoperta di servizio non è riuscita eccezione:

Per il rilevamento dei servizi fallito eccezione, in chat servizio Bluetooth, ho controllato la versione SDK e per la versione SDK, che è maggiore di Ginger Bread,

I ho usato la classe Method per invocare la connessione socket RfCOMM e la mia prima eccezione è risolta in questo approccio.

Codice di eccezione

tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

eccezione fisso codice

try { 
if (Build.VERSION.SDK_INT < 9) { 
try { 
    tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
     } else { 
    Method m = null; 
    try { 
    m = device.getClass().getMethod("createRfcommSocket", 
     new Class[] { int.class }); 
      } catch (NoSuchMethodException e) { 
       e.printStackTrace(); 
       } 
       try { 
        tmp = (BluetoothSocket) m.invoke(device, 1); 
       } catch (IllegalArgumentException e) { 
        e.printStackTrace(); 
       } catch (IllegalAccessException e) { 
        e.printStackTrace(); 
       } catch (InvocationTargetException e) { 
        e.printStackTrace(); 
       } 
       } 
      } catch (Exception e) { 
       Log.e(TAG, "create() failed", e); 
      } 

2. java.io. AzzeratoIOException: software ha causato l'interruzione della connessione di controllo

ho fatto se l'InputStream è disponibile

Codice di eccezione

bytes = mmInStream.read(buffer); 

Codice di eccezione fisso

if (mmInStream.available() > 0) { 
          // Read from the InputStream 
          bytes = mmInStream.read(buffer); 

Ora il mio problema è quando provo a trasmettere i dati tra i dispositivi collegati, getta il seguente messaggio di errore "Connessione ripristinata dal peer" durante la scrittura di flusso di output

Codice di eccezione:

public void write(byte[] buffer, int start, int end) { 
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); 
    if (mmOutStream !=null) { 
     try { 
      mmOutStream.write(buffer); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
    else{ 
     Log.e("OutputStream Null",""); 
    } 
} 

== Aggiornamento ==

Anche se dimostra che entrambi i dispositivi sono collegati, il metodo restituisce accettare sicuro

**06-19 10:30:23.625: D/BluetoothChatService(2630): connected 
06-19 10:30:23.625: D/BluetoothChatService(2630): cancel Thread[AcceptThread,5,main] 
06-19 10:30:23.625: V/BluetoothSocket.cpp(2630): abortNative 
06-19 10:30:23.625: V/BluetoothSocket.cpp(2630): ...asocket_abort(50) complete 
06-19 10:30:23.625: V/BluetoothSocket.cpp(2630): ...accept(50, RFCOMM) = -1 (errno 125) 
06-19 10:30:23.632: E/BluetoothChatService(2630): accept() failed 
06-19 10:30:23.632: E/BluetoothChatService(2630): java.io.IOException: Operation Canceled 
06-19 10:30:23.632: E/BluetoothChatService(2630): at android.bluetooth.BluetoothSocket.acceptNative(Native Method) 

risposta

1

Ho avuto un sacco di problemi con l'esempio di chat, quindi ho provato un altro approccio.

Per prima cosa devi rendere un dispositivo host e l'altro il client, questo funziona abbastanza bene con l'esempio. se non lo fai, posso darti anche quel codice.

Utilizzando le classi sopra, si ottiene il socket per la connessione. Usalo per passarlo a questa classe e poi puoi inviarlo usando il metodo di scrittura. ed i messaggi in arrivo vengono automaticamente analizzati nel periodo precedente metodo (ho aggiunto un ID messaggio e la lunghezza al fronte, ecco perché c'è cose così tante cose in là)

private class ConnectedThread extends Thread { 

/** the connection socket */ 
private final BluetoothSocket mmSocket; 

/** input stream for incoming messages */ 
private final InputStream mmInStream; 

/** output stream for outgoing messages */ 
private final OutputStream mmOutStream; 

/** 
* save the socket and get the streams 
* 
* @param socket 
*/ 
public ConnectedThread(BluetoothSocket socket) { 
    mmSocket = socket; 
    InputStream tmpIn = null; 
    OutputStream tmpOut = null; 

    // Get the input and output streams, using temp objects because 
    // member streams are final 
    try { 
     tmpIn = socket.getInputStream(); 
     tmpOut = socket.getOutputStream(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    mmInStream = tmpIn; 
    mmOutStream = tmpOut; 
} 

/** 
* reads incoming data and splits it into single messages 
*/ 
public void run() { 
    /** buffer for a single byte message */ 
    byte[] buffer = new byte[1024]; 

    /** number of bytes returned from read() */ 
    int bytes; 

    // Keep listening to the InputStream until an exception occurs 
    while (true) { 
     try { 
      // read overhead from the InputStream 
      bytes = mmInStream.read(buffer, 0, LEN_SIZE + LEN_TYPE); 

      // if no bytes are read, wait for a new message 
      if (bytes == 0) 
       continue; 

      // get the size bytes and convert them to int 
      byte[] size_arr = new byte[LEN_SIZE]; 
      for (int i = 0; i < LEN_SIZE; i++) 
       size_arr[i] = buffer[i]; 
      int size = convertByteArrayToInt(size_arr, LEN_SIZE); 

      // the type is 1 byte after the size 
      byte type = buffer[LEN_SIZE]; 

      // array for the output data 
      byte[] output = new byte[size + LEN_TYPE]; 
      output[0] = type; 

      // current position, read until cPos == size 
      int cPos = 0; 
      while (cPos < size) { 
       // either read the buffer lenght or the remaining bytes 
       int read_len = Math.min(buffer.length, size - cPos); 
       bytes = mmInStream.read(buffer, 0, read_len); 

       // write the bytes to the output 
       for (int i = 0; i < bytes; i++) 
        output[cPos + i + LEN_TYPE] = buffer[i]; 

       // increase the current position 
       cPos += bytes; 
      } 

      // add the message to the queue 
      mMessageData.add(output); 

      // tell the service about the new message 
      mHandler.obtainMessage(BluetoothService.CONNECTION_RECV_MSG, mConnectionAddress).sendToTarget(); 

     } catch (IOException e) { 
      // tell the service about the disconnect 
      mHandler.obtainMessage(BluetoothService.CONNECTION_LOST, mConnectionAddress).sendToTarget(); 
      e.printStackTrace(); 
      break; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

/** 
* writes a byte stream to the connection 
* 
* @param bytes 
*   the byte stream 
*/ 
public void write(byte[] bytes) { 
    try { 
     mmOutStream.write(bytes, 0, bytes.length); 
     mmOutStream.flush(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

/** 
* close the socket 
*/ 
public void cancel() { 
    try { 
     mmSocket.close(); 
    } catch (IOException e) { 
    } 
} 

}

questo ha funzionato per me, spero lo faccia anche per te. Se avete qualche domanda, sentitevi liberi di chiedere :-)

+0

Grazie per la risposta, si prega di consultare il mio aggiornamento in questione, grazie –

+0

Quali sono '' LEN_SIZE' e LEN_TYPE' qui, @ gtRfnkN? – ericn

+0

poiché si invia sempre un flusso di byte, non è possibile sapere dove inizia il messaggio e dove finisce. per questo, è necessario estendere il messaggio con il proprio protocollo, compresa la lunghezza del messaggio che si desidera inviare. quindi ho aggiunto 4 byte all'inizio del messaggio per la lunghezza (LEN_SIZE). quando ricevo un messaggio, prima leggo questo valore e poi aspetterò che tutti i dati vengano letti. (vedi while (cPos gtRfnkN

0

Si potrebbe provare questo, anche se probabilmente non dovrebbe essere una soluzione definitiva. Quando ho seguito questo esempio, ho avuto questa onResume() nella mia attività principale, e immagino di avere qualcosa di simile:

@Override 
public synchronized void onResume() { 
    super.onResume(); 
    if(D) Log.e(TAG, "+ ON RESUME +"); 
} 

Prova questo:

@Override 
public synchronized void onResume() { 
// super.onResume(); 
    if(D) Log.e(TAG, "+ ON RESUME +"); 
} 

Questo fermerà l'attività principale di creare l'AcceptThread più di una volta.

0

Penso che la tua lettura sia sbagliata. Ho la linea

while (true) { 
    try { 
     // read overhead from the InputStream 
     bytes = mmInStream.read(buffer, 0, LEN_SIZE + LEN_TYPE); 

nel mio codice e sta funzionando perfettamente, senza .Available() e così fa @gtRfnkN. Dalla mia interpretazione della documentazione Java, non è possibile utilizzare .available() con InputStream. Vedere: http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#available() in particolare la parte in cui viene indicato "sempre restituisce zero per la classe InputStream".

E nel caso, ecco un esempio della mia scrittura:

public void write(byte[] buffer){ 
     try{ 
      //a delay of 20ms occurs after each flush... 
      mmOutStream.write((byte)buffer[0]); 
      mmOutStream.flush(); 
      try { 
       Thread.sleep(20); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
Problemi correlati