Detect when Android kills an AsyncTask - android

If I have an AsyncTask running indefinitely and Android decides it needs to kill the task either to free up memory or because the device is going into sleep mode (the user presses the power button), is there some way within the AsyncTask to get a notice from the OS that it is about to be killed off, so that action can be taken to complete any outstanding task?

To give you a short answer:
an AsyncTask lives as long as the process it is tied to lives. The OS will never kill an AsyncTask if its process is still running (even in background).
Also please note that the AsyncTask runs independently from the Activity that started it. The Activity may be destroyed and the AsyncTask still lives until the process is destroyed.
EDIT
You need to call the isCancelled() inside the doInBackground() method in order to make sure that when the AsyncTask is destroyed by the OS, the doInBackground finishes so that the onCancelled() method is executed.
So to sum it up: in the doInBackground method always check the isCancelled boolean function. If it returns true, then return from the doInBackground. Automatically, the onCancelled function will be executed instead of onPostExecute. There you may place the code you want to execute prior to its death.

Related

How long do Android worker threads last?

I have seen some postings on this subject, but none of them have satisfactory answers.
Assume that I start a worker thread from my main (one-and-only) Activity, in its onCreate() method. Then I call finish() to cause the Activity to terminate.
At that point, the task it belongs to gets destroyed (since there are no longer any Activity in it). The app (and the process running it) may continue to exist, however, in empty "skeleton" form, so that it can be restarted quickly if desired (although it would be highly susceptible to being killed by the system).
Assuming the above is correct -- when is the worker thread killed? Is it only killed when the system actively destroys the process?
In my case, my worker thread exists as a listener for a Bluetooth connection; when received, it will fire up the desired Activity again. In this situation there is no actively running component (Activity, Service, ContentProvider or BroadcastReceiver). It seems to me that this should work, except that something is killing my worker thread.
I am aware that I could do this (and with less pain) by using a background Service. However, I'm curious about why this isn't working.
Thanks,
Barry
when is the worker thread killed? Is it only killed when the system actively destroys the process?
-> the worker thread is skilled after all its code in run function executed. It still run even when your activity is destroyed.
In my case, my worker thread exists as a listener for a Bluetooth connection; when received, it will fire up the desired Activity again. In this situation there is no actively running component (Activity, Service, ContentProvider or BroadcastReceiver). It seems to me that this should work, except that something is killing my worker thread.
To make it works, You need to have a background service in this case and make a soft/weak reference to your service from your worker thread or more simple, using EventBus to start any component from your Service as:
EventBus.getDefault().post(new BlueToothEvent()); // call in your worker thread
// do something in your service
onBlueToothEventFired(BlueToothEvent e);
Android App lifecycle has a nice example that is very on topic:
A common example of a process life-cycle bug is a BroadcastReceiver
that starts a thread when it receives an Intent in its
BroadcastReceiver.onReceive() method, and then returns from the
function. Once it returns, the system considers the BroadcastReceiver
to be no longer active, and thus, its hosting process no longer needed
(unless other application components are active in it). So, the system
may kill the process at any time to reclaim memory, and in doing so,
it terminates the spawned thread running in the process.
In short, its really not very predictable if you thread would get a chance to run until termination or process will be killed beforehand, you should NOT definitely rely on any order/behavior.
Worth mentioning separately that its fairly easy to leak your activity along with thread even if you finish() it, but if its your last/only activity it does not change the picture
When you start a thread, it is independent of the parent that started it. In your case, it is your application activity. This means that until the Run method has been fully executed, your thread will live.
If you exit the application (and therefore call the activity's onStop method), the thread will still exist, and you will cause a memory leak. It will eventually get killed by the system if you run out of memory.
Since you mentioned that you created a listener to listen for a Bluetooth connection, your thread probably dies before it receives any event (It is impossible for me to know without any code snippet). It might also crash which would be ending the thread.
There is one main (also called UI) thread in Android. That is the only thread your app uses, unless it starts one explicitly via Thread.start(), AsyncTask.execute() etc. All Activities, Services, BroadcastReceivers, etc run all of their lifecycle methods on that main thread. Notice I included Services- a Service runs on the main thread unless it starts its own Thread (the exception to that is an IntentService, which does run on its own Thread).
A Thread you create continues until the Runnable its passed returns from its run function (or of course the process is terminated). This can live past the end of the Activity/Service it was created by. However such a Thread would still live in the original instance of the component, and would not be able to access variables of a new instance if one was restarted without a lot of special work (see Loader pattern).

Async task stopped when App terminates (onDestroyed is called)

I have an activity in which I do server sync with a back end server using a subclass of asyctask.
Given it is a network task and might take couple of seconds. I am afraid of the following scenario to take place.
The activity starts, and whenever the asynctask should start to run, it does so.
The onPrexecute() is called, executed, and over. Than the doInBackground() is called, and is done so, however, just when the method is being executed, the user presses the home button and swipes the app from the RECENT APPS. (this ofcourse causes the app to terminate and all the onDestroy methods get called of the alive activities..(Correct me if I'm wrong on this one)).
In my onPostExecute() method, I am inserting the data to DB and updating the VIEWs.
But since the app is 'terminated' the onPostExecute() method never runs.
my questions are :
When the user presses the home button and gets out of the app and swipes the app, is doInBackground halted at that moment ? that is, it is cut in the middle and does not continue what it does ?
What happens to the data that I was going to get from the server and put inside the DB ? Is it advisable to do put the data in the db inside the doInBackground ?
AsyncTask is a background task it will continue to run even if the app is closed and onDestroy() is called. The problem would be when the task enters onPostExecute() and tries to update any views associated with the activity it is bound to, as that activity no longer exists. If you're concerned about this, one thing I've done is to keep a reference to that AsyncTask in the calling activity, and then call the method myAsyncTaskReference.cancel(true) to cancel it in the onDestroy() of the calling activity.
Yes, I would put the DB operations in the doInBackground() method, as that runs in the background on a separate thread, and doesn't require a reference to the app activity.
Have you considered using a service for this type of thing instead? I would strongly recommend an IntentService, which is a subclass of service which is specifically designed to perform a single task in the background (similar to AsyncTask), and then kill itself once completed. It's quite easy to implement and usually only involves overriding one method - onHandleIntent() - which is called when the service starts.
It can handle all your DB operations and it has no reference to an activity and so the problem you're worried about in #1 would never occur. If you need to update a view, you can have your IntentService generate a broadcast once it's completed, and your Activity can register for that broadcast and update it's views accordingly when it receives it. And if your activity is no longer around once the broadcast is sent then it doesn't matter and nothing will fail.
When user presses 'Home', your Activtiy will pause but doInBackground will NOT, but may or may not terminate by system when system feels like it. Activity's onPause will be called. Your Asynctask doInBackGround will NOT halt. It will continue to run until the system kills your App process.
Yes, Db operations can take long. Its advisable to put in doInBackground because it runs on another Thread. onpre/onpostexcute runs on the main thread. If you are worried that System may terminate half way of your db operations, you shouse set Transcation, and only when you are done, you called commit.
Check out this post, I have tested it.
no, it doesn't stop.
It is relly better to put it to datastorage of some kind and then work with it
It is always better to use service for such goals. AsyncTasks just don't fit here. Ask your service to do the work, and then you may start or quit activities as you wish to.
If swiping app from recent stack, it is equivalent to close the app hence it will kill all tasks related to the process so async task will also get killed by the android system. ( even intent service is also get killed)
It is device dependent also. Manufacturers customised removing app from recents behaviour

Does doInBackground still run if my app is in the background?

I have a launcher style app from within which you can launch another app. While that app is launched, I want my app to make note of some things, basically record time etc.
So I have a segment of code whose structure basically looks like this:
appSelectedListener{
runSelectedApp;
private class Background extends AsyncTask<Void, Void, Void>{
protected void doInBackground(){
//executable code
}
}
}
Something alone those lines, I'm sorry if the code is off but I don't actually have anything written yet I just want to get a handle on this stuff first. My question is, when the selected app is brought to the foreground, my app goes to the background. Does the executable code in doInBackground() still get run though? Or would my app necessarily have to be in the foreground?
Does the executable code in doInBackground() still get run though?
Usually. The behavior of threads you fork is not immediately affected by foreground/background considerations.
Eventually, the process for your backgrounded app will be terminated, to free up memory for other apps, or because the user requested that the process be terminated. At that point, all background threads (and everything else you have in RAM) go away. If you have an AsyncTask that has not yet gotten to doInBackground(), doInBackground() will not be called in this case.
To clarify: it's a bit of a misnomer to say that doInBackground() "runs in the background". It runs on a separate thread from the UI thread, but in the same process as the rest of your app (except for any components that you run in a separate process). The UI thread is the highest priority, and the Android system takes steps to ensure that other threads and processes don't interfere with it.
When an event causes a new activity's UI thread to take priority, all other UI threads pause. Other non-UI threads may or may not continue, depending on various factors.
Also, remember that when the user changes the device's orientation, Android's default behavior is to call the onDestroy() followed the onCreate() methods for the activity. This will destroy the AsyncTask object, which destroys the non-UI thread being used to do work asynchronously, which in effect cancels the execution of the code in doInBackground().
For this reason, you should use AsyncTask to do short operations that you don't mind repeating if they get cancelled before finishing. Long-running operations (such as downloading from a server) should be done by an IntentService or sync adapter.

Android background thread and activity relation?

My android app uses AsyncTask to download some data from a website.
But when I press the back button of my android device immediately after the activity starts, worker thread's onPostExecute method is called, which is wierd because android called onDestroy method prior to onPostExecute and the onPostExecute method runs on the main UIThread which I think doesn`t exist anymore.
Can anyone help me what I don`t understand?
An AsyncTask is basically executing what you want in the background as a separate thread from the UI. So when you quit the UI this doesn't necessarily mean that you've killed the AsyncTask. It will continue it's regular life cycle and end in onPostExecute. If you want to kill the AsyncTask too then you will have to call the cancel() function for the AsyncTask.
Know this though, you cannot actually kill an AsyncTask this will be done by Android itself. So you will have to wait a while till the current task is killed (if you call cancel()) for you to restart this particular AsyncTask.
You should also read up on onCancelled() methods. For more information checked out the documentation.
If I've made any mistakes, please correct me.

order of operations when a Service gets shut down

I'm writing a Service that uses an AsyncTask to do some network operations. Let's say the doInBackground of the AsyncTask is taking a very long time, and while that's happening, resources get low and the operating system is shutting down the Service.
When does the AsyncTask get killed? Will the AsyncTask still be running when onDestroy is called, or will it happen afterwards, or am I responsible for shutting down the AsyncTask? I'm trying to make sure I do not have race conditions between the code in my onDestroy and the code in my doInBackground.
The AsyncTask will continue running until either you cancel it or the system destroys the process hosting it. The system doesn't know, per se, about your AsyncTask so its not going to do anything about it when shutting down the Service, it certainly doesn't know the Service created the AsyncTask.
Its very likely that after onDestroy is called that the application's process will be destroyed as well and so will the AsyncTask. However, the safest policy is to be proactive and cancel the AsyncTask in onDestroy.
A perhaps interesting side note is that requests queued for processing will be lost if the process dies before they are processed. As such, any operations sent to an AsyncTask that must be completed need to be written to a persistent task log so they can be reissued if not completed.

Categories

Resources