2013-06-11 14 views
5

Pobrałem próbkę aplikacji czatu Bluetooth do przesyłania tekstu między dwoma urządzeniami z Androidem za pomocą Bluetooth.Nie można wysłać danych tekstowych między dwoma urządzeniami bluetooth w systemie Android?

Mam zainstalowany i uruchomić tę aplikację na dwóch urządzeniach z systemem Android.

ja w obliczu wielu problemów w tym kodzie

  1. odkrycie usługi nie powiodło się wyjątek - Poprawiono
  2. java.io.IOException: Oprogramowanie spowodowało przerwanie połączenia - Fixed
  3. java.io.IOException : Połączenie resetowane przez Peer - Uderzył w to

1. wyczyszczone odkrycie usługi nie powiodło się wyjątek:

Do wykrywania usług powiodło wyjątku, Bluetooth Chat Service, Sprawdziłem wersję SDK dla wersji SDK, który jest większy niż Ginger Bread,

I użyłem klasy Method, aby wywołać połączenie z gniazdem RfCOMM, a mój pierwszy wyjątek został rozwiązany w tym podejściu.

kod wyjątku

tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

Fixed Wyjątek kod

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. Wyczyszczone java.io.IOException: Oprogramowanie spowodowało przerwanie połączenia

zrobiłem sprawdzenie czy InputStream jest dostępny

kod wyjątku

bytes = mmInStream.read(buffer); 

kod Fixed Wyjątek

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

Teraz mój problem jest gdy próbuję wysłać dane między podłączonymi urządzeniami, to rzuca się następujący komunikat o błędzie „Połączenie zostało zresetowane” podczas pisania do strumienia wyjściowego

kod Wyjątek:

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",""); 
    } 
} 

== Aktualizacja ==

Mimo to pokazuje, że oba urządzenia są podłączone, Accept metoda powraca nie

**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) 

Odpowiedz

1

Ja sam miałem wiele problemów z przykładem czatu, więc spróbowałem innego podejścia.

Najpierw trzeba wykonać jednego hosta urządzenia, a drugi klienta, to działa całkiem dobrze. jeśli nie masz tego działającego, mogę ci dostarczyć ten kod również.

Korzystając z powyższych klas, otrzymasz gniazdo do połączenia. Użyj go, aby przekazać go do tej klasy, a następnie możesz wysłać za pomocą metody zapisu. i przychodzące wiadomości są automatycznie przetwarzane w okresie metodą (I dodaje identyfikator i długość wiadomość do przodu, to dlaczego jest tak wiele rzeczy dzieje się w tam)

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) { 
    } 
} 

}

To działało dla mnie, mam nadzieję, że to również dla ciebie. Jeśli masz jakieś pytanie, możesz zapytać :-)

+0

Dzięki za odpowiedź, patrz mój Aktualizacja w pytaniu Dzięki –

+0

Jakie są '' LEN_TYPE' LEN_SIZE' i tutaj, @ gtRfnkN? – ericn

+0

ponieważ zawsze po prostu wysyłasz strumień bajtów, nie wiesz, gdzie zaczyna się wiadomość i gdzie się kończy. Aby tego dokonać, musisz przedłużyć wiadomość o własny protokół, w tym długość wiadomości, którą chcesz wysłać. więc dodałem 4 bajty na początku wiadomości dla długości (LEN_SIZE). podczas odbierania wiadomości najpierw odczytuję tę wartość, a następnie czekam, aż wszystkie dane zostaną odczytane. (patrz while (cPos gtRfnkN

0

Możesz spróbować tego, chociaż prawdopodobnie nie powinno to być ostateczną poprawką. Kiedy następuje ten przykład, miałem ten onResume() w moim głównej działalności, i wyobrażam sobie, że masz coś podobnego:

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

spróbuj tego:

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

To zatrzyma główną działalność od tworzenia AcceptThread więcej niż raz.

0

Myślę, że twoje czytanie jest złe. Mam linię

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

w moim kodu i działa doskonale, bez .available() i tak nie @gtRfnkN. Z mojej interpretacji dokumentacji Java nie można korzystać .available() z InputStream. Zobacz: http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#available() szczególnie część, w której jest napisane "zawsze zwraca zero dla klasy InputStream".

I tak na wszelki wypadek, Oto przykład mojego napisz:

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(); 
      } 
Powiązane problemy