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.
Related
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).
I have a BroadcastReceiver (or, more specifically, an AppWidgetProvider) in which I need to do some network operations in the onReceive() method... not particularly long-running (should finish within 10s, and if not then I'm happy(*) to time them out).
At present I'm executing an AsyncTask from onReceive() so that the network operations don't block the UI thread, but I see that a BroadcastReceiver also provides a goAsync() method for apparently much the same purpose.
I'm struggling to find an explanation as to what exactly the differences are between using AsyncTask and goAsync() in this context... when would you use one, and when the other?
(*) I mentioned that my network operations and subsequent processing would typically finish within the 10s (**) that I understand you have before the BroadcastReceiver is killed (after returning from onReceive()). However, ideally it would be good to allow the operations to continue beyond the 10s in particularly challenging conditions (unreliable network, slow device). Is either of the above methods any better than the other in this respect? At least for goAsync(), the docs suggest that you should still wrap things up within the 10s. But for AsyncTask is it ever possible to spawn the AsyncTask and have the doInBackground() method run beyond the 10s... will it have an existence beyond the lifetime of the BroadcastReceiver if it is declared as a static inner class of the BroadcastReceiver?
(**) EDIT: the 10 second thing is in the docs for BroadcastReceiver.onReceive()... specifically:
When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed).
AsyncTask in receiver is a bad practice, try to avoid it because the system can kill your process and onReceive no guarantee its return.
goAsync() returns a PendingResult object,
the system considers the receiver as alive until you call the PendingResult.finish() on it.
goAsync:
if you call goAsync before the BroadcastReceiver::onReceive return, when a new broadcast comes after a while, android system will call the same receiver, just the same receiver instance where you call goAsync
AsyncTask:
if you call AsyncTask before the BroadcastReceiver::onReceive return, when a new broadcast comes after a while, the android system may call a new receiver even though the process is still running, you may not suppose the receiver is the same as the previous one where you call AsyncTask
I'm having great difficulty understanding when to use Service vs IntentService in Android.
I'm trying to create a Manager Class that can, download, verify and install APKs.
The process of doing this require me to spawn a service(DownloadManager) to download the file, which causes my service to be destroyed prematurely.
It also needs to run an activity to install the apk.
This download manager has no front end, I just want it to be a background process that does its thing and returns the results programmatically.
I've read into both Service and Intent Service and although the documentation clearly says that Intent Services are meant to be used when the processing should be done off the UI thread, but nearly every forum I visit says that you should not do async work inside an IntentService.
For example:
Waiting for asynchronous callback in Android's IntentService
In general, an IntentService is useful for when you have discrete tasks that you want executed one at a time off of the UI thread. The IntentService will keep track of each request in a queue, execute one request at a time - on a separate, non-UI thread - and then will shut down when the queue is empty. If a new request arrives later, it will start up again, then shut down again once the queue is empty.
The warnings about running "async" work inside of an IntentService are because once onHandleIntent exits, the IntentService thinks that item has finished processing. It has no way of knowing if you created another thread that you want it to wait for. So once it has called onHandleIntent for all outstanding requests, it's going to shut down, even if there are child threads still running.
A non-intent Service gives you control over when the service starts and stops, regardless of whether there's any work to do. Also, unless you specifically make it otherwise, everything the Service does happens on the UI thread - so if you want work done on a background thread, you need to explicitly implement that. It's also up to you to implement how the Service handles multiple incoming requests. But, the service won't shut down until you tell it to (or the OS runs out of resources).
It sounds based on your description like you probably have two choices:
If you're ok with the service processing requests one at a time, you could use an IntentService - but you'll need to make onHandleIntent wait for each request to finish. This is still happening off of the UI thread, but it does mean that if you have multiple download requests, they're not going to happen in parallel.
You could use a non-intent Service to process each download request on its own child thread, all in parallel. Then it's up to you to keep track of all the processing threads.
I have an AsyncTask executed from a service. Since AsyncTask runs in a separate thread, I have few doubts:
What would happen if service onStartCommand() method returns while the AsyncTask is executed ? Does the service shut down while AsyncTask is executed ?
How to best resolve this situation ?, should I use START_STICKY ?
Since onPostExecute() runs on UIThread, Will it run on same thread as service's onStartCommand method ? What would happen in above case if AsyncTask is still running while service shuts down. Which thread would onPostExecute() upon ?
Update:
The reason I am using Service is because Service is instantiated from a onReceive method of a Broadcast Receiver. I would agree that I could just use an ordinary thread in onReceive but the service-AsyncTask pattern seems to be a better one because I need to fire some notifications as well which I am doing in onPreExecute and onPostExecute.
I have an AsyncTask executed from a service
Since you rarely need to work on the main application thread in a Service, I would recommend just using an ordinary thread.
What would happen if service onStartCommand() method returns while the AsyncTask is executed ?
Nothing.
Does the service shut down while AsyncTask is executed ?
onStartCommand() is called when the service is sent a command. It is not called when the service is being shut down.
should I use START_STICKY ?
That is impossible to answer in the abstract. Use it if you need the service to be restarted later on (e.g., when the available memory improves).
Since onPostExecute() runs on UIThread, Will it run on same thread as service ?
Objects do not run on threads in Java. Hence, a service does not run on a thread. Methods run on threads.
What would happen in above case if AsyncTask is still running while service shuts down.
That is up to you, as you are the only one that shuts down the service.
If the OS gets rid of the service for other reasons, it will tend to do so by terminating the entire process, in which case the AsyncTask is gone too.
Which thread would onPostExeucte() upon ?
onPostExecute() runs on the main application thread. Since this is rarely needed, or even a good idea, in a Service, please consider using an ordinary thread rather than an AsyncTask.
Better yet, use an IntentService, if your work is transactional in nature (e.g., needs to run for several seconds, then the work is done and the service is no longer needed), as IntentService comes with its own background thread, so you do not need yours.
UPDATE
The reason I am using Service is because Service is instantiated from a onReceive method of a Broadcast Receiver
That has nothing to do with anything.
I need to fire some notifications as well which I am doing in onPreExecute and onPostExecute.
You can raise a Notification from a background thread. You do not need to do it from the main application thread.
I am a little confused about AsyncTask and Thread life cycle.
What happens to a processes threads when the OS enters the OnStart/OnStop and onResume/onPause sequences.
Are the threads affected by this sequence.
I ask this question because I am using sockets in the threads and killing the threads will kill the tcpip connections as well (I assume).
If the thredas are not killed then how do I 'reconnect' to them especially as they may will be 'connected' to an activity via a Handler.
Threads are not automatically killed when the app goes to onStop or onPause, however, there is no guarantee it won't be killed. Android will keep it running until it needs the resources that the thread is using.
Generally, if you want a persistent connection when an Activity closes, then put that in a Service. You can run threads in it just like an Activity (to prevent blocking that usually occurs with connections), and it's far less likely Android will kill it.
Internally, AsyncTask uses fixed thread pool. (See http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html )
So, even if AsyncTask finished, thread does not die. But thread in thread pool can be killed.