Android show dialog from background thread in any activity of application - android

I tried to look clear answer for it but wasn't able to find it anywhere. I am running background thread in main activity that checks for certain variable and if it is true it should show alert dialog. I also want this dialog to show up on any focused activity of the application. I tried it by adding Looper.prepare() and Looper.loop() to the thread but it does not work properly and it affects while() loop that I use to check variable in that thread. Can anyone please help me in finding out what is the best way to implement this?
Thanks.

If you construct the background thread using the main/ui thread, you can create a Handler in the constructor. When you want to run some code on the main/ui thread, you simply Handler.post(Runnable r) with a runnable to the ui thread.
If your background thread is not being constructed on the ui/main thread, you can use a BroadcastIntent to and a BroadcastReceiver pattern to send messages between your background thread and your foreground activities. This is especially useful if you are switching foreground activities during the useful life of your background thread.

You may want to try creating an implementation of Runnable and passing that to a View's post() method.
final Runnable r = new Runnable() {
public void run() {
//code to display dialog
}
}
final View view = findViewById(R.id.XYZ);
view.post(r);
This will run the Runnable on the UI thread.

Ok, i can see two approaches. The first one is a dirty but quick:
You can extend TimerTask and Handler classes. YourTimerTask will check variable and send a Message to YourHandler. YourHandler should override handleMessage and show a dialog.
The second one might be an overkill, but still. Android is event-based. It means that system gives you an opportunity to create your own events and handle it. So, you can start a Service, which will check your variable and send a Broadcast (can be local). In your activity you have to create your own BroadcastReceiver and register it. This receiver will handle a message.

Related

How to perform a delay on a non-UI Thread in Android

So, there are multiple similar questions/answers about how to do a delay on Android. However they mostly focus on doing this on UI thread.
What if I need a delay in a worker thread in a service (and I don't want to put the thread to sleep)? the Handler.postDelayed() doesn't work as there is a "can't create a handler inside thread has not called Looper.prepare()" exception. CountDownTimer doesn't work for the same reason. And I don't have any views to call runOnUiThread().
So is the only solution to have a looper on each thread I have or there is another way to do this?
UPDATE:
It's silly, but I found the answer working for me in my own old code :).
Basically, if you want to start a Runnable with a delay from a non-UI thread, all you need to do is ask the main looper to handle this.
Handler handler = new Handler(Looper.getMainLooper());
Runnable r = new Runnable() {
#Override
public void run() {
// Do stuff to be run after a delay
// CAUTION: this won't be run on the same thread
}
};
handler.postDelayed(r, DELAY_TIME);
The drawback could be that the code in that Runnable will not be run on the same thread as the original code. This is why I'm not putting this approach as an answer to be accepted (I admit, the original question sounded like I want a timed event to happen on the same non-UI thread. For this I don't have an answer yet except the one from Emmanuel that I must attach a Looper to my thread). For my purposes however this works as I only need to start a service upon timeout.
Like you have seen from the Exceptions in order to use Handlers in a Thread you need to attach the Thread to the Looper. To give a bit more context, when you call postDelay() you are posting a message to the Thread's MessageQueue; the Looper is responsible for managing this Queue. So if you want to go the Handler route you will need to set up the Thread with a Looper.
If you want to delay the Thread without making it sleep() (I do not know why you cannot use sleep()) you can have a while that runs until a certain time from now has elapsed. (This sounds like a horrible idea).

Using SpeechRecognizer in a service-only application. Running code on the main thread

I'm developing an application that is meant to run only as a service. That is, it has no Activity (that is usually run, at least), and at any given moment, the only component of the application that will be running (usually) is a service. This is meant to be used with the screen locked. It already works.
In such a scenario, I seem to understand that the service's thread is the application's "main thread", even though it's not a UI thread proper (as there is no UI).
The question is: if the service uses a HandlerThread, can I call runOnUIThread() from a method that is called from the HandlerThread? Will this make it run from the main thread, without the need to launch an Activity (which would involve unlocking the screen)?
Basically my problem is that I need to use a SpeechRecognizer, lanching it from the service.
Right now my service is using a Handler on a HandlerThread. When trying to init a SpeechRecognizer from methods that are (indirectly) called by the HandlerThread, I get an exception because SR has to be run from the main thread.
Can I use runOnUIThread()?
I see there is a similar question here: How to invoke Speechrecognizer methods from service with no main thread or activity
However, the answer involves invoking the SR from onCreate() or onStartCommand(), which is not viable in my case.
UPDATE: obviously, I can not call runOnUIThread(), as it is a method of Activity. So is there a way to have some call run on the main thread, which is in this case not a UI thread?
This answer is not speech-recognizer specific which is why it started as a comment, but more space is needed to clarify...
Handler mainHandler;
public void onCreate() {
super.onCreate();
mainHandler = new Handler(); // this is attached to the main thread and the main looper
// ...
}
// anywhere in a background thread:
mainHandler.post(new Runnable() {
// ...
});
This code creates a handler which is attached to the main thread. Posting to this handler from a background thread will run code on the main thread as desired.
I'm not using SpeechRecognizer so I can't guarantee that it will solve the problem, but it seems like it should.
Edit: some more detail
The article I was thinking of that explains some big ideas is The Android Event Loop. In particular it links to this bit of code which shows how runOnUiThread is implemented by posting to a Handler as I am suggesting here:
/**
* Runs the specified action on the UI thread. If the current thread is the UI
* thread, then the action is executed immediately. If the current thread is
* not the UI thread, the action is posted to the event queue of the UI thread.
*
* #param action the action to run on the UI thread
*/
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}

Is there a callBack to SetContentView in Android?

Is there any callBack to setContentView in Android, since i'm doing a heavy operation right after setContentView line, and it seems to skip that setContentView.
So i was thinking of moving the heavyOperation to the callBack of setContentView.
Thanks
EDIT:
Pseudo Code:
AudioRecord Finishes
SetContentView(1) //To show a "Processing" screen with no buttons
FFT analysis
SetContentView(2) //On FFT analysis DONE.
In my case "SetContentView(1)" NEVER occurs.
EDIT # 2:
I did the heavy operation in another Thread, and used Handler to send a Message after heavy operation finishes to treat it as a callBack.
Thanks for all the help guys
Short answer: No callback for the setContentView.
If you are doing network operation then you can use the AsyncTask for this.
If you are doing any more heavy operation and want to update the UI then you can do that using the Service and BroadCastReceiver.
For this you have to make your own callback using the interface.
heavy work should be done in asynk tasks or as a service or on other threads
Don't do any heavy calculations on the main UI thread where onCreate() and such are run.
What happens that the first setContentView() posts a "layout and draw" message to the UI thread message queue. Then your calculation blocks the UI thread, preventing messages in the queue from being processed. The second setContentView() posts another message to the queue. When the control eventually returns to the message loop, both messages are processed and you'll get the layout set up by the last call to setContentView().
For heavy computations, use a separate thread. For example, an IntentService or an AsyncTask make threading easier.
My hack.
final Handler handler = new Handler();
setContentView(layoutResID); // This posts some messages to message queue.
handler.post(new Runnable() { // Post another message at the end.
#Override
public void run()
{
// Called after layout has changed.
// If you want to skip some more works (like transitions),
// call another handler.post() here.
}
});
To see what happens, set a break point at the line Message msg = queue.next(); in Looper.loop() may help.
I was facing a quite similar problem a day ago, but I figured it out. (I know your problem is solved, just offering a different approach which doesn't require a handler or callback.
Most Suitable for running U.I. functions :
If you need to do something like this :runTask() then
setContentView() (or any other ui function) you can run the task on different thread by using AsyncTask or you can set a timer for when the task is completed (if your task takes a certain time), the User Interface functions will be called.
But since the Timer class, runs the functions on a different thread, you can not run the setContentView() inside it. So you can use a runOnUiThread(Runnable action) method inside the overloaded run() function of Timer class. You just need to define a function that returns a runnable. Define your Ui operations in the runnable action.
Hope it helps someone.

Updating UI of Android activity from some other class running on different thread

I have a activity with a Listview and a adapter attached to it. I have a class which syncs data and hold it. (I think we should not care about from where data is coming) and it runs on a different thread. Now I want to know the clean way to update adapter but We should not call any function of activity from that class as it runs on different thread.
One way I know is to create handler in activity and pass it to other class and use it from there. But I want to know if activity is in background then activity's function can be called by UI thread or only when activity come in foreground.
I do not want to miss any update and want to update activity when it is in foreground.
If you want to update your listView from another class you can have a few ways to do that.
Send broadcastIntent from your worker class and add BroadcastReceiver to your activity and when you receive the right message, update your listview.
Second way is to create private or public class in your Activity which extends AsyncTask and in your doInBackground() do your work and in onPostExecute(result) update your listview.
Third way which I can imagine, but I don't think it's the best way create a static method is your activity which you can use from any other class for updatiogn your UI.
The best thing which you can use here at least in my opinion is AsyncTask.
this code will do what you want:
runOnUiThread(new Runnable() {
#Override
public void run() {
//your actions
}
});
We should not call any function of activity from that class as it runs on different thread.
That's wrong. (in java an object is not running in a thread. What you can say is that a method is running in the thread from which the method was called)
In Androïd (and in most UI frameworks) the rule is this:
You can only call a method updating UI from the UI thread.
If you have some code running on a thread (not the ui thread) and if that code need to update the UI : you can use the Handler of the UI-thread to post UI update code to the UI-thread. If the activity is not in the foreground when you post something to update it's UI : nevermind! the code you just post will be executed at some point in the future.
You should use AsyncTask, take a look at http://developer.android.com/reference/android/os/AsyncTask.html

Does posting a Runnable with a Handler make things asynchronous?

I am updating an activity's UI from a BroadcastReceiver that I register in the same activity. The API docs say:
[...] The function [onReceive()] is normally called within the main thread
of its process [...]
so I suppose updating the UI is okay.
The docs also say:
[...] you should never perform long-running operations in it (there is
a timeout of 10 seconds [...]
I am just setting some text on a TextView so I suppose that won't ever take longer than 10 seconds.
But, and here comes finally my actual question: Does it make any sense at all to add a Runnable to the main thread's message queue using a Handler, so that onReceive() can return immediately and the UI update happens at some later point in time, as the docs suggest:
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; [...]
?
If you're just setting text on TextViews then you won't have issues. No need to over-complicate things with Handlers.
Though I will say that some people like using handlers just because it keeps things organized if multiple calls to a specific UI method need to be called. Using a handler will guarantee that that executed code will be initially placed on the UI thread, so it avoids having to check which thread you are running on.
The important thing to keep in mind is that all UI actions should be performed on the UI thread, and any sort of intensive processing should be done on a background thread.
Yes, using a Handler to schedule a Runnable is the standard.

Categories

Resources