Accessing UI thread handler from a service
AndroidMultithreadingUser InterfaceServiceHandlerAndroid Problem Overview
I am trying some thing new on Android for which I need to access the handler of the UI thread.
I know the following:
- The UI thread has its own handler and looper
- Any message will be put into the message queue of the UI thread
- The looper picks up the event and passed it to the handler
- The handler handles the message and sends the specfic event to the UI
I want to have my service which has to get the UI thread handler and put a message into this handler. So that this message will be processed and will be issued to the UI. Here the service will be a normal service which will be started by some application.
I would like to know if this is possible. If so please suggest some code snippets, so that I can try it.
Regards Girish
Android Solutions
Solution 1 - Android
This snippet of code constructs a Handler associated with the main (UI) thread:
Handler handler = new Handler(Looper.getMainLooper());
You can then post stuff for execution in the main (UI) thread like so:
handler.post(runnable_to_call_from_main_thread);
If the handler itself is created from the main (UI) thread the argument can be omitted for brevity:
Handler handler = new Handler();
The Android Dev Guide on processes and threads has more information.
Solution 2 - Android
Create a Messenger
object attached to your Handler
and pass that Messenger
to the Service
(e.g., in an Intent
extra for startService()
). The Service
can then send a Message
to the Handler
via the Messenger
. Here is a sample application demonstrating this.
Solution 3 - Android
At the moment I prefer using event bus library such as Otto for this kind of problem. Just subscribe the desired components (activity):
protected void onResume() {
super.onResume();
bus.register(this);
}
Then provide a callback method:
public void onTimeLeftEvent(TimeLeftEvent ev) {
// process event..
}
and then when your service execute a statement like this:
bus.post(new TimeLeftEvent(340));
That POJO will be passed to your above activity and all other subscribing components. Simple and elegant.
Solution 4 - Android
I suggest trying following code:
new Handler(Looper.getMainLooper()).post(() -> {
//UI THREAD CODE HERE
});
Solution 5 - Android
You can get values through broadcast receiver......as follows, First create your own IntentFilter as,
Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");
Then create inner class BroadcastReceiver as,
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
/** Receives the broadcast that has been fired */
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction()=="YOUR_INTENT_FILTER"){
//HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
String receivedValue=intent.getStringExtra("KEY");
}
}
};
Now Register your Broadcast receiver in onResume() as,
registerReceiver(broadcastReceiver, intentFilter);
And finally Unregister BroadcastReceiver in onDestroy() as,
unregisterReceiver(broadcastReceiver);
Now the most important part...You need to fire the broadcast from wherever you need to send values..... so do as,
Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);
....cheers :)
Solution 6 - Android
In kotlin
thats how you can do it
Let say if you want to show Toast message from service
val handler = Handler(Looper.getMainLooper())
handler.post {
Toast.makeText(context, "This is my message",Toast.LENGTH_LONG).show()
}
Solution 7 - Android
Solution:
- Create a Handler with Looper from Main Thread : requestHandler
- Create a
Handler
withLooper
from Main Thread: responseHandler and overridehandleMessage
method - post a Runnable task on requestHandler
- Inside
Runnable
task, call sendMessage on responseHandler - This
sendMessage
result invocation of handleMessage in responseHandler. - Get attributes from the
Message
and process it, update UI
Sample code:
/* Handler from UI Thread to send request */
Handler requestHandler = new Handler(Looper.getMainLooper());
/* Handler from UI Thread to process messages */
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
/* Processing handleMessage */
Toast.makeText(MainActivity.this,
"Runnable completed with result:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
for ( int i=0; i<10; i++) {
Runnable myRunnable = new Runnable() {
@Override
public void run() {
try {
/* Send an Event to UI Thread through message.
Add business logic and prepare message by
replacing example code */
String text = "" + (++rId);
Message msg = new Message();
msg.obj = text.toString();
responseHandler.sendMessage(msg);
System.out.println(text.toString());
} catch (Exception err) {
err.printStackTrace();
}
}
};
requestHandler.post(myRunnable);
}