Change notification in AsyncTask - android

I have an AsyncTask which creates a Notification and updates it while the progress.
But when the user exists my aplication while the AsyncTask is working, i loose the Context and I can't update anymore.
So would it be a good idea to change the function of the back button to the same function as the home button while the AsyncTask is running? Or what is another way to still have access to a Context?

I tend to avoid AsyncTasks for reasons like this. I normally use them for things that if either the activity or the task dies nothing is lost. For things that I want to make sure that will finish incase the Activity dies or if there is a problem with the background work you should probably use a Service. The platform has a basic one built in called the IntentService. This should work well for your situation since the Service will have its own context and can update and track Notifications itself.
Another alternative, which I wouldn't recommend but it is possible, is to have the main Application keep a reference to itself in a static variable. That'll also provide a Context that the task can use.

Related

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.

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

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.

timer for a social app

I am writing a social game but am stuck with how to create a timer thread that works accross activities showing time lapse for an attribute such as energy. Every activity has the energy textview but the thread can update only one view at a time. Please note that im not using androids timer class but have created my own thread class.
You probably don't want to try to keep a thread running between activities. Managing it when the activity suspends will give you nothing but headaches. It's much easier to just store your time in the Application while you move from activity to activity. The Application is alive for the duration, no matter which Activity is actually loaded. The fact that you have an identically named TextView in various activities is neither here nor there... it's not the "same" TextView... it just looks (and smells) similar. So, you can just grab the clock when the app first launches and at any given time look at the difference between the current time and that time.
Then just use a Timer to update the string in whatever Activity you're in.
If you're unfamiliar with Application it's going to be a real Eureka thing for you to discover (Android tutorials overlook it ALL the time, for some reason, leaving you to do all sorts of really ugly Intent passing alternatives).
If you have any questions on how to use it, just follow up in a comment, and I'll add details.
I think you must think about using a Service :
Thus a Service itself is actually very simple, providing two main
features:
A facility for the application to tell the system about something it wants to be doing in the background (even when the user is not
directly interacting with the application). This corresponds to calls
to Context.startService(), which ask the system to schedule work for
the service, to be run until the service or someone else explicitly
stop it.
A facility for an application to expose some of its functionality to other applications. This corresponds to calls to
Context.bindService(), which allows a long-standing connection to be
made to the service in order to interact with it. When a Service
component is actually created, for either of these reasons, all that
the system actually does is instantiate the component and call its
onCreate() and any other appropriate callbacks on the main thread. It
is up to the Service to implement these with the appropriate behavior,
such as creating a secondary thread in which it does its work.

Android - Run in background - Service vs. standard java class

In Android, if I want to do some background work, what is the difference between
Creating a Service to do the work, and having the Activity start the Service
VS.
Creating a standard java class to do the work, and having the Activity create an object of the class and invoke methods, to do the work in separate thread.
Doing your own threads is overkill, there are solutions for this, so you don't have to worry about the hard parts of concurrency. Have a look at AsyncTask or IntentService. If you go for a service please keep in mind that your service can be killed at any time.
Well, Android provides some useful methods for making worker threads easily. Look at the Looper class definition. It allows you to send events via a Handler to be executed one after another in another thread or transmit messages between different threads.
A service is nothing fancy. Creating a Service is just a way of telling the OS that you need to do some work even when your Activity is not visible.
Depending on the application you're building it might not be an option.
Nearly every network application will have some of its functionality on a Service to allow the user change active Activity while something is being downloaded.
In an RSS reader, for example you can click 'Update all' and, depending on the current data connection, it might take a bit longer than you wish. So if you want the user to be able to get back to the Home screen and do anything else while the files are being dowloaded you'll have to use a Service.
A Service allows you to run tasks on the background while the user is not on your Activity. This doesn't mean it'll be running all the time. Check the Service lifecycle.
BTW IntentService is a service.

Categories

Resources