I've created a service class and a worker class that is executed in a separate thread. I would like to setup a communication between them, so the worker could send some status back to the service.
I've tried to convert my worker Thread
to HandlerThread
and setup a Handler
on the service side, but then I don't know how to actually send a message from the worker. It looks like I can't grasp the concept.
Here's my classes (without communication logic):
Service class
package com.example.app;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class ConnectionService extends Service {
protected ConnectionWorker thread;
@Override
public void onCreate() {
super.onCreate();
// Creating a connection worker thread instance.
// Not starting it yet.
this.thread = new ConnectionWorker();
Log.d(this.getClass().getName(), "Service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(this.getClass().getName(), "Service started");
// Checking if worker thread is already running.
if (!this.thread.isAlive()) {
Log.d(this.getClass().getName(), "Starting working thread");
// Starting the worker thread.
this.thread.start();
}
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.d(this.getClass().getName(), "Stopping thread");
// Stopping the thread.
this.thread.interrupt();
Log.d(this.getClass().getName(), "Stopping service");
super.onDestroy();
Log.d(this.getClass().getName(), "Service destroyed");
}
}
Worker class
package com.example.app;
import android.os.SystemClock;
import android.util.Log;
public class ConnectionWorker extends Thread {
public ConnectionWorker() {
super(ConnectionWorker.class.getName());
}
@Override
public void run() {
super.run();
Log.d(this.getClass().getName(), "Thread started");
// Doing the work indefinitely.
while (true) {
if (this.isInterrupted()) {
// Terminating this method when thread is interrupted.
return;
}
// @todo: send a message to the service
Log.d(this.getClass().getName(), "Doing some work for 3 seconds...");
SystemClock.sleep(3 * 1000);
}
}
}
How do I implement a HandlerThread
, send messages from the worker thread and receive them in my service?
I will highly appreciate a code example.
Update
Actually, it looks like I can't use Looper
inside of my thread cause it will block the thread execution and I don't want that. Is it possible to send messages from the thread without using Looper
?
Slava, actually, your answer doesn't work. Let me explain why.
Why does Android have HandlerThread when Thread already exists?
This is because as the documentation says, HandleThread is a
How is a Looper used to create a Handler?
A Looper should be passed in the Handler's constructor to tell the Handler which Looper it is working with.
So each HandlerThread has one Looper and there can be many Handlers handling messages the Looper loops through.
When you created a new Handler in your Service class using the default constructor, the Handler gets associated to the current Looper, as explained in it's documentation.
You can confirm the problem still exists using by printing this
at appropriate places - within the Service's
onCreate()
, within the Handler'shandleMessage()
and within therun()
of ConnectionWorker. How to solve your problem then?You can create a HandlerThread, even within the service, and when it's Looper is ready, create the Handler using that Looper.
Hope it isn't too late an answer :P
It looks like I've finally nailed it!
In order to pass data from thread back to a service you will need to do this:
Subclass a
Handler
class inside of your service (call it e.g. aLocalHandler
). You will have to make it static. Override ahandleMessage
method, it will receive messages from the thread.Add a
Handler
argument to yourThread
constructor. Instantiate yourLocalHandler
class in a service and inject it to your thread via constructor.Save reference to the
Handler
inside of your thread and use it to send messages whenever appropriate.Here's the complete example:
Service Class
Worker Class (Thread)
I hope it's a valid implementation. If you now a better approach - please let me know.