Async task stopped when App terminates (onDestroyed is called) - android

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

Related

What will happen if tasks take long time in onStop()

Consider I want to save some data in database in onStop() method of my app and I use AsyncTask to execute queries , or doing any kind of tasks that take long time to perform , so what will happen ? Does activity wait to complete task ? my tasks will be done correctly ?
p.s: I want to do this (saving data in onStop() ) because I dont want to execute query each time user click on a button and change something , I want to do it at the end .
thanks in advance .
An AsyncTask started in onStop will run to completion. There shouldn't be any problems with that. If it takes a really long time it may be restarted before it finishes, which could cause issues in your program depending on how you coded.
If the onStop function itself takes too long, you could trip a watchdog timer and your app may be killed.
First asynctasks are guaranteed to run to completion. but you should note that they can work tightly in synch with UI and you can modify some ui elements in the call backs of asynchTask (onProgressSubmit(), onComplete()...) but if you UI thread is not available on the event of these callbacks you may get an exception.
Second in some rare situations (low memory) in old APIs prior to API11 on stop method may not get called so it is better to save you data in another call back such as (on pause).

Long-running task when activity is destroyed

I want to run a network request once user closes an app i.e. onStop and onDestroy is called on app's activity. The problem is I also want to wait for response from server and save some data locally after I get it so the whole procedure may need to be finished after the app is fully closed.
Is there any kind of background service in Android which won't be terminated after app is closed and will be waiting for requests's completion (for some reasonable time at least)?
The solution is Non UI fragment. Here is an example I have created:
https://github.com/kadymuhammad/Non-UI-Fragment .
You can also see this answer https://stackoverflow.com/a/21336010/5186466
Using Asynctask inside a Non UI fragment will continue to run even if the activity is paused but i will stop if the app task stopped.
The perfect solution is to use Service or IntentService classes.
Check this out :
http://www.tutorialspoint.com/android/android_services.htm

Handling background tasks and activity configuration changes

Here is problem which I'm trying to solve for three days:
For example, REST client app perfoms a lot of background work (network calls) and posts result back to UI thread. It is obvious that it should be done asynchronously. Android allows to do this in several ways (for example AsyncTasks and IntentServices).
The biggest problem of running asynchronous tasks from activity is configuration change.
For example we have activity which starts download process in AsyncTask and shows ProgressDialog. After screen rotation, activity is being recreated by OS. As the result when asynctask will try to dismiss progressdialog of old (dead) activity, it will fail.
There are several solutions to this problem:
first one is to retain asynctask in worker fragment: Great post how to do that is here. Big advantage of this solution is that OS knows when to call onPostExecute() method. In some cases onPostExecute() maybe called in moment when old activity is destroyed and new one is still not created. But that doesn't happen because OS doesn't allow execution of onPostExecute() before onAttach() is called. Disadvantage is that AsyncTasks are not suitable for long term operations and behaves differently depending on OS version.
the second approach is using LocalBroadcastManager and IntentService. Here is another post which shows how to use it. What will happen if service will send message to BroadcastReceiver when it is unregistered (the moment when activity is being recreated)?
the third solution is dirty hack: declare this in mainfest android:configChanges="keyboardHidden|orientation". Is not appropriate for me.
Maybe someone knows another solution?
You can prevent screen orientations before the task with setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) and restore it after.
The othet other idea is a service. You're worried that when one orientation is closed and before the other is loaded you may miss a broadcast. In that case the service should store the data somewhere the fresh activity can load it. (SqlLite, a file, sharedPrefs)
Also note broadcastRecievers can be registered in the manifest. So always on, so to speak.

Should I use intent service?

I have a user login screen. The user presses a login button and I create an IntentService to connect to my rest services and return back a authentication result.
Now here's the functionality I want to achieve: If the activity is paused (i.e. goes into the background) then the intent service should still run, and it does. But if I use the task manager to kill the application, the intent service should stop, although right now it doesn't. It continues executing onHandleIntent until complete. If I manually call stopSelf(), onDestroy() is called but the onHandleIntent method continues to execute. How do I force the onHandleIntent to stop? Calling "return" is not an option because it could be caught up in one rest method call.
Should I be using intent service for this functionality or something else (like service or asynctask)?
First off, if your service is doing something that you want done while your app is running in the foreground, then you don't need a Service. Your activity or dialog can just spawn a thread to do your task, and these threads will end when your app ends, since they are within the task scope of your app. Otherwise, for tasks you want done all the time, when the user could be doing anything on the device, definitely use a Service.
I'm not sure why "calling return" is not an option for you? By this I assume you mean checking for a condition, and exiting the loop or block if the condition is met. This is generally how threads (in services or elsewhere) should end (although there are other approaches). Your service's thread can listen to a specific event that has occurred (like if the activity has been destroyed, by setting a property in a file or database when the activity's onDestroy is called, though if this is what you want then you probably should NOT use a Service), and then run() can return gracefully.
But if this is a task you want done no matter what the user is doing on his device (within or outside of your app), then it should be a task that should not be interrupted from the outside. It should keep going until it's done.
Maybe if you could better define when you want this service to be stopped?
stop it in your onDestroy() method

AsyncTask doubts regarding the activities flow

I got some concerns about AsyncTask that I could not clarify when reading the documentation.
My app main Activity runs several AsyncTask's when it's created. These AsyncTask's mostly download data or retrieve data from the DB.
If I go to a different Activity, will the AsyncTask's created on
this one continue executing? Or will they stop working and leave the
task half done? If so, will they go on somehow when getting back to
this activity?
In order to start one of the activities from the
one that is running the AsyncTask's, I need one of the AsyncTask's
to be fully executed. How do I set this constraint? Could you show
me some sample code of this, please?
Thanks
If I go to a different Activity, will the AsyncTask's created on this one continue executing? Or will they stop working and leave the task half done? If so, will they go on somehow when getting back to this activity?
Yes, it will continue to run. This can be a bit of a double-edged sword as it will typically also hold on to the Activity instance, causing it to live beyond its onDestroy() callback, which is not ideal. If the task you are running does not have the same lifecycle needs as the Activity itself, it may be better placed into a Service.
In order to start one of the activities from the one that is running the AsyncTask's, I need one of the AsyncTask's to be fully executed. How do I set this constraint? Could you show me some sample code of this, please?
There are way too many ways to do this, many depending on the architecture of your application, to provide specific sample code...but here are a few higher level ideas. Since AsyncTask provides a simple callback method on the main thread (onPostExecute) when the task execution is complete, you can set a flag at that point. Or perhaps simply check for the existence of whatever data the AsyncTask is retrieving from any code where the Activity would be launched. Again, a Service would provide good context for this, as multiple Activities could connect to the service and check the task status before moving forward.
Another option, depending on your application, is to have the result of the task dumped into a ContentProvider. ContentProviders include a nice interface for notifying observers of changes without resorting to global Broadcast Intents.
HTH
Ive done something similar to this before using Intents and Broadcast Receivers.
If you get the Async tasks to send a global or app-wide intent when they are finished, its easy enough to have a receiver pick it up if you construct them properly. By having a receiver created when you push a new activity onto the stack, and have the receiver close when an activity is paused, there will always be a receiver out there to grab the intent and be told that the (example: data is downloaded from the db) and act on that.
If you try and start an activity that requires that data, you can either deny the creation of that activity if the intent hasn't been found yet, or create the activity and have it put up a progress bar or something while the data finishes downloading, then have its receiver act on the intent when it arrives.
Hope this helps.

Categories

Resources