简体   繁体   中英

How can I keep a connection thread alive? (Do I need to use a daemon?)

My Android application uses a thread to listen for a sockets connection from a PC connected via USB. At some point after the PC opens the connection (in response to some user driven event) I want to send some data over it.

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();
    }
}.

For ages I was scratching my head wondering why I never saw the value of INNER_TAG appear in my logs after touch events. I could use log-debugging to trace the execution into the coordHandler!=null block, but the handler never seemed to fire.

Then it struck me: the thread is probably exiting after completing the connection. D'uh! Not quite sure what I thought was happening before, but I'll blame it on a belief that Loop was doing something magical.

So my question is: How can I keep my thread running? The official Android dev reference on threads briefly mentions that

A Thread can also be made a daemon, which makes it run in the background.

This naturally made my *nix senses tingle. (Incidentally, have you seen the new Spiderman film yet? It's pretty good.) Is daemonisation the answer? Or have I completely lost the plot?

Use Service in Android.

You can use Service to run at the background..

See this link:

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

See this link for the example:

Example: Communication between Activity and Service using Messaging

  1. Change connection = new Thread(new ServerThread()); to: connection = new ServerThread();

  2. Maybe add synchronized blocks when setting/getting handler instance (it is in different threads after all :))

  3. Loop actually does the magic ;)

  4. In onDestroy quit Looper for serverThread

  5. And last but not least (although it does not concern Handler/Looper subject is probably the reason why you never see in logs what you expect): instead of boolean onTouchEvent(MotionEvent event) use boolean dispatchTouchEvent(MotionEvent ev) as onTouchEvent due to docs is Called when a touch screen event was not handled by any of the views under it. so probably this handler method is never called

EDIT: Are you sure it executes sendMessage? And by the way why do you use Log.v ? it assumes you have logging level set to verbose otherwise the logs will be abandoned. I suggest to use rather Log.i .

Maybe try this code:

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM