2012-02-10 27 views
7

Mam aplikację, która używa bluetooth do odbioru niektórych danych (bajtów) z innego urządzenia. wszystko idzie dobrze, ale mam mały problem z otrzymaniem wszystkich bajtów. Po otrzymaniu bajtów pokazuję je na toście, aby je przetestować. Kiedy drugie urządzenie wysyła razem 10 bajtów (na przykład: "ABCDEFGHIJ"), program pobiera tylko pierwszy bajt "A" i pokazuje go na toście, następnie przechodzi do drugiej iteracji i odczytuje pozostałe 9 bajtów i pokazuje " BCDEFGHIJ "na grzance. Tu jest mój kodu:Jak czytać wszystkie bajty razem przez 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; 
    } 
} 

W główną działalność, mam:

// 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; 

      // ... 
     } 
    } 
}; 

Jak mogę odbierać wszystkie bajty razem ?!

+0

Mogę zobaczyć jak jesteś wysyłanie wiadomości? Czy robisz coś takiego jak bOutStream.write ("ABCDEFGHIJ" .getBytes()) lub czy wypisujesz znaki po jednym na raz? – broody

+0

Moduł bluetooth jest podłączony do arduino, więc używam monitora szeregowego oprogramowania arduino do wysłania wiadomości. –

Odpowiedz

6

Mmm najprawdopodobniej winowajcą jest sposób, w jaki wysyłasz wiadomości. Twoje otrzymanie nie ma problemów, otrzyma tyle bajtów (aż do twojego 1024), jak to jest napisane.

Jeśli nie masz kontroli nad sposobem wysyłania wiadomości, prawdopodobnie możesz odczytać jeden bajt na raz, a następnie wysłać komunikat obsługi, gdy trafisz predefiniowany terminator. Np .: "ABCDEFGHIJ #" gdzie # jest terminatorem.

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

+1 Dobre rozwiązanie. Będę korzystał z tego rozwiązania, dopóki nie znajdę innego sposobu na rozwiązanie problemu. Dzięki! –

+0

Co się stanie, jeśli prześlę dane binarne? Jak mogę się upewnić, że terminator nie jest częścią strumienia danych? – stoefln

4

Połączenie Bluetooth jest oparte na strumieniu, a nie na pakiecie. Nie ma gwarancji ani próby zachowania pakietów. Tak więc dowolna liczba zapisów może spowodować dowolną liczbę odczytów, po prostu strumień bajtów jest gwarantowany. Jeśli chcesz wykryć pakiety, musisz podać własną strukturę pakietów, aby zawinąć swoje dane. Na przykład dodaj pole długości przed każdym pakietem danych, aby móc zrekonstruować po stronie odbiorczej.

+0

+1 To także jest dobre rozwiązanie. Dzięki! –

+0

@ TJD A skąd mam znać długość pola długości? – stoefln

-1

Sposób, aby obsługiwać dłuższe niż bufor wiadomości (może być niebezpieczne, ponieważ może potrwać swoją pamięć, jeśli nie wyczyszczone) ma obsługiwać je w kawałki:

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

to nie pomoże mi przeczytać wszystkich wiadomości w buforze –

+0

kod zakłada ";" jest ogranicznikiem wiadomości. kod jest przykładową implementacją i nie jest uniwersalny - nie można go kopiować i wklejać i oczekiwać pracy bez modyfikacji, ale pokazuje koncepcję.i czyta wszystkie wiadomości. po osiągnięciu końca wiadomości handler.sendMessage (msg); jest wywoływana, aby obsłużyć kompletny komunikat i przetwarzanie bufora jest kontynuowane. Musisz wdrożyć procedurę obsługi, aby przetworzyć/przeczytać wiadomości. taka jest koncepcja –

2

Zaakceptowanych odpowiedź jest poprawna od @broody . Jeśli jednak same dane zawierają "#", pobranie danych może być trudne. Tak więc najlepszym podejściem według mnie jest dołączanie '\ n', po którym następuje '\ r' (lub dowolne inne znaki, które prawdopodobnie nie będą funkcjonować jako dane Refer ASCII Table) w Urządzeniu, które wysyła dane do twojej aplikacji Android. Działa tylko jako Line feed i zaznacza koniec danych.

Np ABCDEFGH \ n \ r

Następnie kod może być coś takiego:

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++; 
} 

Nadzieja pomaga Pozdrowienia

+0

** Brilliant **! To rozwiązało mój problem, bez dodawania dodatkowego znaku '# 'po stronie Arduino. Po prostu pominąłem test dla '\ r' (sprawdzam tylko dla' \ n') i działa jak charm. –

Powiązane problemy