4

私の Android アプリケーションは、スレッドを使用して、USB 経由で接続された PC からのソケット接続をリッスンします。PCが接続を開いた後のある時点で(ユーザー主導のイベントに応答して)、データを送信したいと思います。

public void onCreate(Bundle savedInstanceState) {

    // SNIP: stuff and nonsense

    connection = new Thread(new ServerThread());
    connection.start();
}

public boolean onTouchEvent(MotionEvent event) {

    // SNIP: decide what to do; create string 'coordString'

    Message coordMsg = coordHandler.obtainMessage();
    Bundle coordMsgData = new Bundle();
    coordMsgData.putString("coords", coordString);
    coordMsg.setData(coordMsgData);
    if(coordHandler!=null)
    {
        coordHandler.sendMessage(coordMsg);
    }

    return false;
}

public class ServerThread extends Thread
{   
    public void run() {

        this.setName("serverThread");

        Looper.prepare();

        coordHandler = new Handler()
        {
            @Override
            public void handleMessage(Message msg) {
                Log.v(INNER_TAG,"here");
            }
        };

        // SNIP: Connection logic here

        Looper.loop();
    }
}.

何年もの間、私は、なぜINNER_TAGタッチ イベントの後に の値がログに表示されるのを見たことがないのかと頭を悩ませていました。ログデバッグを使用して実行をcoordHandler!=nullブロックに追跡することはできましたが、ハンドラーが起動することはありませんでした。

それから私は驚いた:スレッドはおそらく接続の完了後に終了している. ああ!以前に何が起こっていたと思っていたのかはよくわかりませんが、Loop魔法のようなことをしていると信じていたせいにします.

私の質問は次のとおりです。どうすればスレッドを実行し続けることができますか? スレッドに関する公式のAndroid dev リファレンスには、次のことが簡単に述べられています。

スレッドは、バックグラウンドで実行されるデーモンにすることもできます。

これは当然私の*nixの感覚をうずきました。(ちなみに、新しいスパイダーマンの映画はもう見ましたか? かなり良いです。) デーモン化が答えですか? それとも、プロットを完全に失ってしまったのでしょうか?

4

2 に答える 2

2

Android でサービスを使用します。

Service を使用してバックグラウンドで実行できます。

このリンクを参照してください。

http://developer.android.com/reference/android/app/Service.html

例については、次のリンクを参照してください。

例: メッセージングを使用したアクティビティとサービス間の通信

于 2012-07-11T18:59:14.117 に答える
0
  1. 変更connection = new Thread(new ServerThread());:connection = new ServerThread();

  2. ハンドラーインスタンスを設定/取得するときに同期ブロックを追加するかもしれません(結局、別のスレッドにあります:))

  3. ループは実際に魔法を行います;)

  4. onDestroy で serverThread の Looper を終了します

  5. そして最後に重要なことを言い忘れました (ハンドラー/ルーパーの件名には関係ありませんが、おそらくログに期待するものが表示されない理由です): docs のために onTouchEvent としてboolean onTouchEvent(MotionEvent event)使用する代わりに、おそらくこのハンドラー メソッドは呼び出されません。boolean dispatchTouchEvent(MotionEvent ev)Called when a touch screen event was not handled by any of the views under it.

編集: sendMessage を実行してもよろしいですか? ところで、なぜあなたは を使うのLog.vですか?ロギング レベルが verbose に設定されていることを前提としています。それ以外の場合、ログは破棄されます。むしろ使用することをお勧めしますLog.i

多分このコードを試してください:

ServerThread connection;
Handler coordHandler;

public void onCreate(Bundle savedInstanceState) {
    connection = new ServerThread();
    connection.start();
}

@Override
protected void onDestroy() {
    synchronized (this) {
        if(coordHandler != null) {
            coordHandler.getLooper().quit();
        }
    }
    super.onDestroy();
}

public boolean dispatchTouchEvent(MotionEvent event) {

    synchronized (this) {
        if(coordHandler == null) {
            Log.i(INNER_TAG, "Handler is null");
        }
        else {
            Log.i(INNER_TAG, "Handler exists");
            coordHandler.sendMessage(
                    coordHandler.obtainMessage(
                            0, event.toString()));
        }
    }

    return false;
}

synchronized void setCoordHandler(Handler handler) {
    coordHandler = handler;
}

public class ServerThread extends Thread {

    public void run() {

        this.setName("serverThread");

        Looper.prepare();

        setCoordHandler(new Handler() {

            @Override
            public void handleMessage(Message msg) {
                Log.i(INNER_TAG, "Inside handler");
            }
        });

        Looper.loop();
    }
}
于 2012-07-11T21:51:30.683 に答える