Bluetooth経由でPCと通信するAndroidアプリを書いています。通常の動作中、電話機から PC に短い 8 バイトのパケットを高速で連続して送信します。通常は 100Hz を超えます。
各デバイスでは、書き込みと読み取りを実行する個別のスレッドが実行されています。コードは次のようになります。
/**
* The Class ProcessConnectionThread.
*/
public class ConnectedThread extends Thread {
/** The m connection. */
private StreamConnection mmConnection;
InputStream mmInputStream;
OutputStream mmOutputStream;
private boolean mmCanceled = false;
/**
* Instantiates a new process connection thread.
*
* @param connection
* the connection
*/
public ConnectedThread(StreamConnection connection) {
mmConnection = connection;
// prepare to receive data
try {
mmInputStream = mmConnection.openInputStream();
mmOutputStream = mmConnection.openOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Thread#run()
*/
@Override
public void run() {
byte[] buffer;
int bytes;
// Keep listening to the InputStream while connected
while (!mmCanceled) {
try {
buffer = ByteBufferFactory.getBuffer();
// Read from the InputStream
bytes = mmInputStream.read(buffer);
if(bytes > 0)
onBTMessageRead(buffer, bytes);
else
ByteBufferFactory.releaseBuffer(buffer);
} catch (IOException e) {
MyLog.log("Connection Terminated");
connectionLost();//Restarts service
break;
}
}
if(!mmCanceled){
onBTError(ERRORCODE_CONNECTION_LOST);
}
}
/**
* Write to the connected OutStream.
*
* @param buffer
* The bytes to write
* @param length
* the length
*/
public void write(byte[] buffer, int length) {
try {
mmOutputStream.write(buffer, 0, length);
// Share the sent message back to the UI Activity
onBTMessageWritten(buffer, length);
} catch (IOException e) {
MyLog.log("Exception during write:");
e.printStackTrace();
}
}
/**
* Cancel.
*/
public void cancel() {
try {
mmCanceled = true;
mmInputStream.close();
mmConnection.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Android 側のコードはほぼ同じで、ストリーム接続の代わりに BluetoothSocket を使用するだけです。
大きな違いは、onBTMessageRead(buffer, bytes);
アンドロイド機能:
protected void onBTMessageRead(byte[] buffer, int length) {
if (mHandler != null) {
mHandler.obtainMessage(BluetoothService.MESSAGE_READ, length, -1,
buffer).sendToTarget();
}
}
PC サーバー機能:
protected void onBTMessageRead(byte[] message, int length) {
if (mEventListener != null) {
mEventListener.onBTMessageRead(message, length);
}
// Release the buffer
ByteBufferFactory.releaseBuffer(message);
}
Android は、スレッド間でメッセージを送信できるようにするハンドラ ルーパー/メッセージ パターンを提供します。これにより、読み取りが可能な限り高速に行われ、メッセージ処理が別のスレッドのキューに入れられます。私の ByteBufferFactory は、リソースがスレッド間で適切に共有されるようにします。
現在、PC 側に実装されているイベント リスナー パターンしかありませんが、PC 側にも同様のメッセージ パッシング パターンが必要です。現在、イベント リスナーが ConnectedThread を動かなくなっており、大きな通信遅延が発生しています。
Java のあるスレッドからメッセージを送信し、それらを別のスレッドで FIFO 順で非同期に処理する方法はありますか?