How do I get the message queue of the main thread from another thread? Looper.getMainLooper() gets the main thread's looper but I am unable to find a way to get the MessageQueue for another thread's looper. Moreover, how do I get the handler for the main looper? I am unable to find any way to get it.
-
Why? You shouldn't need to mess with the queue directly. – CommonsWare Jul 02 '11 at 19:16
-
I just want to add an idleHandler to check if the main thread is doing something – r.v Jul 02 '11 at 19:48
-
@CommonsWare I somehow want to check if the main thread's messagequeue is empty. I am new to these concepts and was thinking of using idleHandler to get notified when the queue becomes empty. – r.v Jul 02 '11 at 20:00
-
@CommonsWare I am actually working on something similar to Android's stock instrumentation framework but different in the sense that you might be able to control an app from outside its process. For this I needed to implement something that would tell me that the main thread of the app is idle so that I could poke into the view hierarchy of the app and so on. This is something similar to Instrumentation.waitForIdle(). For all this, I indeed have to make changes somewhere in the Android framework but was just trying to minimize those changes. – r.v Jul 02 '11 at 21:06
-
2Then have the main thread register the `IdleHandler` and inform other parties via some sort of listener mechanism. I fail to see the need to have some other thread do this. "For all this, I indeed have to make changes somewhere in the Android framework" -- probably quite a few changes at that. – CommonsWare Jul 02 '11 at 21:13
-
@CommonsWare Here is my use case, I am dealing with an app, that supports you to add multiple apps inside it and users can then use it execute it. They can be RN apps, web apps, native apps. Each app has requirements of its own where they want to initialise their own stuff, some one main thread and some on background. I as a moderator want to do initialisations only when main thread is free. Any solutions that you can think of. – vishal_ratna Aug 24 '22 at 16:18
-
@vishal_ratna: "I am dealing with an app, that supports you to add multiple apps inside it and users can then use it execute it" -- that seems rather impractical, above and beyond security concerns. "Any solutions that you can think of" -- hire quality legal counsel and 100+ developers/security engineers. – CommonsWare Aug 24 '22 at 16:23
-
@CommonsWare You mean to say the app is impractical or my proposal. By apps I mean apps that come to you in slack. They are build by 3rd parties, and can be downloaded by internal app store. They have their optimisation needs, they have their own android components that run inside our app. The internal telemetry suggests that we are doing lots of stuff and we want to moderate that and, I am thinking about providing a framework that provides you opportunities when main thread is free. – vishal_ratna Aug 24 '22 at 16:29
-
"By apps I mean apps that come to you in slack. They are build by 3rd parties, and can be downloaded by internal app store." -- AFAIK, Slack bots and apps work with a restrictive API, not "RN apps, web apps, native apps... they have their own android components that run inside our app". Slack has quality legal counsel and 100+ developers/security engineers. And Slack has its fair share of problems. – CommonsWare Aug 24 '22 at 16:39
-
@CommonsWare the app that I work on is Microsoft Teams, we support RN and Web apps. We provide a shell activity in which these apps can host themselves and we provide them with core APIs. But, all these apps, when installed want to do some kind of pre-warming to make their startup times quicker. Eg. could be, some RN apps ask to pre initialise the react instance, so that when user click on their app they are fast. But if a bunch of apps do it, app startup takes a heavy toll. I am trying to explore if we can do something on the lines I proposed, so that I do not end up shooting in dark. – vishal_ratna Aug 24 '22 at 17:10
-
@CommonsWare We have 400+ developers so things quickly get out of control if not moderated by strong frameworks around it. So was trying to explore this possibility. – vishal_ratna Aug 24 '22 at 17:13
-
@vishal_ratna: Well, you have quality legal counsel and 100+ developers/security engineers, so you're set there! You could see if your thread is an instance of `HandlerThread`. If it is, then you can get its `Looper` via `getLooper()` and call `getQueue()` on that to get the `MessageQueue`. If you're interested in the overall main application thread, `Looper.getMainLooper()` should return that. If you have additional concerns, you might want to open a fresh Stack Overflow question, as this one is over 10 years old. – CommonsWare Aug 24 '22 at 17:19
-
@CommonsWare Sure. I will experiment around these lines and see if I can get to something concrete. Thanks for the inputs. – vishal_ratna Aug 24 '22 at 17:33
3 Answers
@r.v,
I had a similar need. I wanted to know when the MessageQueue is empty and when I post something for it to do and I want to know when it becomes empty with nothing remaining to do. I looked at the MessageQueue.IdleHandler
and found that it didn't behave as I wanted to I came up with another solution.
In my case I wanted to use the Looper/Handler mechanism to sequentially execute file downloads. Basically each download I want to execute is wrapped in a Runnable. I only want one at a time to be running, so this pattern works well without having to dig into the nuts and bolts of a more involved threading solution. Additionally, I wanted to know when I first put something into the queue and it begins its work, and wanted to know when it was completely done (queue is empty).
I was able to use the handler's message mechanism to achieve this. The messages are handled in sequence with the Runnables, so you can strategically place messages in the queue to help you know the conditions of the queue. Unlike with Runnables in the Handler's queue, there are some query and removal abilities for messages that ultimately provide the solution.
What I do is each time I add a runnable to the Handler (via Handler.post
), I also remove all instances of the custom QUEUE_EMPTY
message, then add a fresh QUEUE_EMPTY
message. This ensures that I have a QUEUE_EMPTY
message at the end of the queue. Once I encounter the QUEUE_EMPTY
message in my subclassed Handler, I know that I'm at the end of the queue. Additionally, if I don't find a QUEUE_EMPTY
message in the queue when I go to add a runnable, I know that the queue was empty and the thread was idle.
As some will quickly point out, there are some real inefficiencies with this solution. Having to iterate through the queue for these "marker" messages could be a real performance issue if there were a large number of entries in the queue. In my case, I'm dealing with only a handful of file downloads at a time so any performance penalties are negligible. If you have a similar situation, I think this is a pretty reasonable solution. It would have been nice for the Android SDK to provide these basic abilities to the MessageQueue
. I agree ideally you wouldn't want to mess with the MessageQueue, but knowing when it is idle/working/empty seem like reasonable things and I'm sure there are numbers of scenarios when there is value knowing these things.
class DownloaderThread extends Thread
{
private static final int QUEUE_EMPTY = 9999;
private MyHandler handler;
@Override
public void run()
{
try
{
Looper.prepare();
handler = new MyHandler();
Looper.loop();
}
catch (Throwable t)
{
Log.e(TAG, "halted due to an error", t);
}
}
public void post(Runnable r)
{
if(!handler.hasMessages(QUEUE_EMPTY))
{
Log.v(TAG, "Download queue was empty. First element being added.");
}
handler.post(r);
handler.removeMessages(QUEUE_EMPTY);
handler.sendEmptyMessage(QUEUE_EMPTY);
}
class MyHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
if(msg.what == QUEUE_EMPTY)
{
Log.v(TAG, "Download runnable queue is empty!");
}
}
}
};

- 41,009
- 21
- 145
- 105

- 4,763
- 1
- 25
- 19
After you get the main threads looper, you should just be able to call myQueue to get the main threads MessageQueue.
http://developer.android.com/reference/android/os/Looper.html#myQueue%28%29

- 180
- 7
-
The documentation says it returns the current thread's MessageQueue and I want to get it on a thread different from the main thread. – r.v Jul 02 '11 at 18:49
-
Sorry, I misread the question. MessageQueue is an internal structure, and I'm not sure if Android allows you to access it directly from outside the thread. What do you want to do with the MessageQueue once you get it that can't be done using the main thread's handler and looper? – RAnderson Jul 02 '11 at 19:28
-
I want to add an idleHandler to check if the main thread is not doing anything. By the way, I also need the handler for the main thread - I have edited my question for this. – r.v Jul 02 '11 at 19:51
-
Use the Handler class to interact with a Looper's message queue.
To interact with the main thread's message queue,
Handler mainHandler = new Handler(Looper.getMainLooper(), new Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
});
mainHandler.post(...);
mainHandler.sendMessage(...);
mainHandler.removeMessage(...);
Now you can send, remove and receive messages.

- 14,186
- 13
- 65
- 103