Accessing UI thread handler from a service
Solution 1
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
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
I suggest trying following code:
new Handler(Looper.getMainLooper()).post(() -> {
//UI THREAD CODE HERE
});
Solution 4
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 5
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 :)
iLikeAndroid
Newly into Android, have experience on mobile programming in Symbian... starting liking Android for its simplicity to implement anything... wanna learn more on Android...;)
Updated on July 08, 2022Comments
-
iLikeAndroid almost 2 years
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
-
iLikeAndroid almost 13 yearsThanks for this tip. This was helpful. Please see the following stack for a touch event flow to my activity MyDemo.dispatchTouchEvent(MotionEvent) line: 20 PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 1696 ViewRoot.handleMessage(Message) line: 1658 ViewRoot(Handler).dispatchMessage(Message) line: 99 Looper.loop() line: 123 //Event handling starts here ActivityThread.main(String[]) line: 4203 Here the ViewRoot is a Handler. I want to get the reference of this handler...is it possible to get this from my application?
-
CommonsWare almost 13 years@iLikeAndroid: If you did not create the
Handler
, you cannot access it, AFAIK. -
iLikeAndroid almost 13 yearsThank you. I have tried to create an instance of ViewRoot. This is nothing but a handler. Now I am able to issue the messages on this handler. The handler is getting the message. But the ViewRoot is not able to process the message as it is not initialized properly. I need to call ViewRoot.setView() to initialize the proper data to ViewRoot. I want to know is there a default view or a base view etc, which I can use to initialise?
-
CommonsWare almost 13 years@iLikeAndroid: There is no
ViewRoot
in the Android SDK, AFAICT. -
mrPjer almost 12 yearsTested it out and it works great! An example of a use case: I have a web interface which is being served by a server running directly on the device. Since the interface can be used to directly interact with the UI, and since the server needs to run on it's own thread, I needed a way to touch the UI thread from outside an Activity. The method you've described worked great.
-
JRun almost 11 yearsBrilliant. Works like a charm, and very useful. THANK YOU.
-
An-droid over 10 yearsperfect ^^ just used it to update my ui from a StreamingService. exactly what i needed thanks !
-
hadez30 over 8 years@CommonsWare - I know this is an old post, but what if the Activity only binds to the service (that's already launched, of course). How would you go about that? Would it be a good practice to send this same handler to the Activity that binds to the service?
-
CommonsWare over 8 years@hadez30: Personally, I don't use bound services much. You're still welcome to use a
Handler
/Messenger
, though I'd replace all that with an event bus (e.g., greenrobot's EventBus). -
hadez30 over 8 yearsI see. Thanks, CommonsWare. Was trying to avoid passing the handlers to Activities upon Activities. I guess that's the way to go. Will finally try using EventBus that I keep hearing about.
-
HelloWorld about 6 yearsdo you know if i can create a singleton instance of a handler, and use that every time i need to run something on the ui thread?
-
Denny over 5 yearsI guess we'll never know
-
volley over 5 years@HelloWorld yes that should work, assuming the Looper returned by Looper.getMainLooper() does not change. Did you try it?
-
HelloWorld over 5 years@volley I don't remember, but I don't think it's relevant to say if it worked or not. To be 100% sure it will always work, the Android documentation should state so explicitly, or one should check the source code to see if it can be deduced :)
-
Moog about 5 yearsSome additional explanation is required to assist the OP.