Accessing UI thread handler from a service

81,096

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 :)

Share:
81,096
iLikeAndroid
Author by

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, 2022

Comments

  • iLikeAndroid
    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:

    1. The UI thread has its own handler and looper
    2. Any message will be put into the message queue of the UI thread
    3. The looper picks up the event and passed it to the handler
    4. 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
    iLikeAndroid almost 13 years
    Thanks 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
    CommonsWare almost 13 years
    @iLikeAndroid: If you did not create the Handler, you cannot access it, AFAIK.
  • iLikeAndroid
    iLikeAndroid almost 13 years
    Thank 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
    CommonsWare almost 13 years
    @iLikeAndroid: There is no ViewRoot in the Android SDK, AFAICT.
  • mrPjer
    mrPjer almost 12 years
    Tested 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
    JRun almost 11 years
    Brilliant. Works like a charm, and very useful. THANK YOU.
  • An-droid
    An-droid over 10 years
    perfect ^^ just used it to update my ui from a StreamingService. exactly what i needed thanks !
  • hadez30
    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
    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
    hadez30 over 8 years
    I 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
    HelloWorld about 6 years
    do 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
    Denny over 5 years
    I guess we'll never know
  • volley
    volley over 5 years
    @HelloWorld yes that should work, assuming the Looper returned by Looper.getMainLooper() does not change. Did you try it?
  • HelloWorld
    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
    Moog about 5 years
    Some additional explanation is required to assist the OP.