How can I keep the connection chain live? (Do I need to use a demon?)

My Android application uses a stream to listen for socket connections from a PC connected via USB. At some point after the PC opens the connection (in response to some event controlled by the user), I want to send him some data.

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 centuries, I have been scratching my head, wondering why I have never seen the value of INNER_TAG in my magazines after touch events. I could use a debug log entry to track execution in the coordHandler!=null block, but the handler never fired.

Then it struck me: the thread probably exited after the connection was completed. D'uh! Not quite sure what I thought before, but I will blame him for Loop doing something magical.

So my question is: how can I save the stream? The official Android dev topic link briefly mentions that

A Thread can also be made a daemon that will launch it in the background.

This naturally made my feelings. (By the way, have you seen the new spider movie? That's pretty good.) Is demonization the answer? Or am I completely losing the plot?

+4
source share
2 answers

Use the Service in Android.

You can use the Service to work in the background.

See this link:

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

See this link for an example:

Example: Communication between Activity and a Service Using Messaging

+2
source
  • Change connection = new Thread(new ServerThread()); to: connection = new ServerThread();

  • Maybe add synchronized blocks when installing / receiving an instance of the handler (it will be in different threads in the end :))

  • The loop actually does magic;)

  • In onDestroy quit Looper for serverThread

  • Last but not least (although this does not apply to the Handler / Looper object, this is probably the reason why you never see what you expect in the logs): use boolean dispatchTouchEvent(MotionEvent ev) instead of boolean onTouchEvent(MotionEvent event) boolean dispatchTouchEvent(MotionEvent ev) as onTouchEvent due to docs 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 is running sendMessage? And by the way, why are you using Log.v ? it assumes that you have a logging level set, otherwise the logs will be left. I suggest using Log.i rather.

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

All Articles