クライアントまたはサーバーが接続を切断するまで、サーバーから受信データを常に読み取るために使用されるTCPクライアントとして使用されるTCPソケットがあります。他の方法はわかりませんが、別の Runnable スレッドでwhile (true)ループを使用し、その中で (while ループで) 着信データをチェックします。受信したデータはEditTextに出力する必要があります。
私が抱えている問題は、Handler.post(...)からテキストを更新することです。
そんなこと知ってる:
Android 3.0 以降で TCP 接続を作成するには、Strict モードがデフォルトで有効になっており、無効にしたくないため、TCP コードをnew Thread(...)またはAsyncTaskに配置する必要があります。
Android で新しいスレッドから UI を更新するには、 Threadを使用する場合は Handler.post() を使用する必要があり、AsyncTask を使用する場合はpublichProgressを介してonProgressUpdateを使用する必要があることを知っています。両方で奇妙なイライラする問題が発生しています。
だから、私がやりたいことは次のとおりです。
- サーバーを永続的にリッスンする
- サーバーが「w」、「a」、または「n」などのメッセージを送信するとすぐに、すぐにそれを EditText に表示します。あなたはそれをtelnetセッションと考えることができますが、私はすべての単一バイトを処理したいので、telnetよりも「より多くの」精度が必要です。一度に 1バイトずつ読み取るか、バイトのバッファーを取得してから、バッファーを反復処理して個別に処理する必要があります。一度にバイトで行きました。
これが私が持っているコードです。handle.response の上の私のコメントに注意して、私が抱えている問題を確認してください。これをクリアしていただければ幸いです。
コードは非常に簡潔にコーディングされており、このサンプルでは多くのエラー チェック セクションを削除しました。
ThreadClientInput: という名前の新しいクラスがあります。
public class ThreadClientInput implements Runnable {
InputStream inputStream;
MainActivity mainActivity;
Handler handler = new Handler();
int NextByte = 0;
public ThreadClientInput(MainActivity ma)
{
mainActivity = ma;
}
@Override
public void run()
{
////////////////////////////////////////////////////////////////
// Run the sensitive code that requires us to create this thread
try {
mainActivity.tcp_Client = new Socket("192.168.1.90", 23);
}
catch (Exception e){Log.e("EXEPTION:", e.getMessage().toString());return;}
////////////////////////////////////////////////////////////////
// Only try to get the inputStream if we have a successful connection
if (mainActivity.tcp_Client != null)
{
try
{
inputStream = mainActivity.tcp_Client.getInputStream();
}
catch (Exception e){Log.e("EXEPTION:", e.getMessage().toString()); return;}
}
/////////////////////////////////////////////
/////////////////////////////////////////////
// Update the text on the "Connect" button
handler.post(new Runnable()
{
@Override
public void run()
{ mainActivity.btn_Connect.setText("Connected");}
});
/////////////////////////////////////////////
/////////////////////////////////////////////
try
{
// I need to constantly read the data until we manually disconnect or
// the server drops the connection
while (true)
{
// Get the next byte
// I do not want to use "readline()" from a BufferedReader etc because I need to know exactly what's coming in
// I need to process every single byte
NextByte = inputStream.read();
if (NextByte > -1)
{
Log.e("in (While loop):", Character.toString((char)NextByte));
*** Here is the problem ****
// Update the EditText and this is where the problem starts
// if the server sends "1234", the Log.e() above will display everything correctly: "1234"
// however the handler.post below will run at the end of the last byte so the
// the EditText as well as the second Log.e below within the handle.post will display: "1444" or "4444" or "2444"
// So the handler.post does *not* run immediately even if I try handle.postAtFrontOfQueue()
// If the server sends "12345678", again, Log.e() above will display everything correctly: "12345678"
// however the handler.post below will run at the end of the last byte again
// and I will get "88888888" (most of the time) or "18888888"
//
handler.post(new Runnable()
{
@Override
public void run()
{
mainActivity.et_Response.setText(mainActivity.et_Response.getText() + Character.toString((char)NextByte));
Log.e("In handler.post:", Character.toString((char)NextByte));
}
});
}
}
}
catch (Exception e){Log.e("EXEPTION:", e.getMessage().toString());}
}}
runOnUiThreadと AsyncTaskを含むさまざまなバリエーションを試しましたが、すべて同じ結果が得られました。私は外出しています、私には何もありません。現時点では、Handle.post メソッドに関するドキュメントを読んで、理解できるかどうかを確認しています。
解決策があることを願っています。「while (true)」は良い習慣ではないことはわかっていますが、フラグを設定してスレッドの外側からループを破ることができます。これを行う方法は他にありません.