2012-02-10 12 views
7

他のデバイスからのデータ(バイト)を受信するためにBluetoothを使用するアプリケーションがあります。すべてうまくいっていますが、バイトをすべて一緒に受信することには少し問題があります。バイトを受け取った後、私はそれらをテストするためだけにトーストに示します。他のデバイスが10バイトを一緒に送信すると(たとえば "ABCDEFGHIJ")、プログラムは最初のバイト "A"のみをトーストに表示し、2番目の繰り返しに進み、 BCDEFGHIJ "をトーストに追加します。ここに私のコードは次のとおりです。MainActivityで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; 
    } 
} 

、私が持っている:

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

      // ... 
     } 
    } 
}; 

は、どのように私は一緒にすべてのバイトを受け取ることができます!

+0

は、私はあなたがあなたのメッセージを送っているかを確認することができ役に立てば幸い? bOutStream.write( "ABCDEFGHIJ" .getBytes())のようなことをやっているのですか、一度に1つずつ文字を書き出していますか? – broody

+0

bluetoothモジュールがarduinoに接続されているため、arduinoソフトウェアのシリアルモニタを使用してメッセージを送信しています。 –

答えて

6

ほとんどの場合、あなたがメッセージを送信している途中です。あなたの受信に問題はありません。それは、書き込まれたバイト数(1024まで)を受信します。

メッセージの送信方法を制御できない場合は、一度に1バイトずつ読み込んでから、定義済みのターミネータにヒットしたときにハンドラメッセージを送信することができます。例: "ABCDEFGHIJ#"#はターミネータです。

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

+1良い解決策。問題を解決する別の方法が見つかるまで、私はこの解決方法を使用します。ありがとう! –

+0

バイナリデータを転送するとどうなりますか?ターミネータがデータストリームの一部ではないことをどのように確認できますか? – stoefln

4

ブルートゥース接続はパケットベースではなくストリームベースです。パケット化を保証するものではありません。したがって、任意の数の書き込みで任意の数の読み取りが行われる可能性があります。バイトストリームだけが正しいことが保証されています。パケットを検出する必要がある場合は、独自のパケット構造を用意してデータをラップする必要があります。たとえば、受信側で再構築できるように、各データパケットの前に長さフィールドを追加します。 (クリアされることはありません場合は、あなたのメモリを取ることができるので、危険なことができます)よりも長いバッファメッセージを処理する

+0

+1これも良い解決策です。ありがとう! –

+0

@TJD長さフィールドの長さはどうやって分かりますか? – stoefln

-1

方法は、チャンクでそれらを処理することです:

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

バッファ内のすべてのメッセージを読むのに役立ちません –

+0

コードは ';'と仮定します。メッセージの区切り文字です。コードはサンプル実装であり、普遍的ではありません。コピー&ペーストすることはできませんし、変更せずに作業することを期待していますが、コンセプトを示しています。すべてのメッセージを読み取ります。メッセージの終わりに達すると、handler.sendMessage(msg);完全なメッセージを処理するために呼び出され、バッファの処理が続行されます。メッセージを処理/読み込むハンドラを実装する必要があります。それはコンセプトです –

2

@broodyから受け入れ答えが正しいですか。しかし、データ自体に「#」が含まれていると、データを取得するのが難しい場合があります。したがって、私の考え方によれば、\ nの後ろに '\ r'(またはデータRefer ASCII Tableとして機能する可能性が低い他の文字)をデバイスに追加して、Androidアプリにデータを送信します。それは単に改行として機能し、データの終わりを示します。

例:ABCDEFGH \ n個の\ rを

次に、あなたのコードは、このようなものになることができます。

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

は、それが よろしく

+0

**ブリリアント**!それはArduino側に余分な '# '文字を追加することなく、私の問題を解決しました。私は単純に '\ r'のチェックをスキップしました(' \ n'をチェックするだけです)、それは魅力のように機能します。 –

関連する問題