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
Change connection = new Thread(new ServerThread());
to: connection = new ServerThread();
Maybe add synchronized blocks when setting/getting handler instance (it is in different threads after all :))
Loop actually does the magic ;)
In onDestroy quit Looper for serverThread
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.