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).
Related
I wonder what conditions must be met so Android stops a Service, besides the obvious, running low on memory.
See, I run a bootstrapping Service, holding a local BroadcastReceiver. The service itself contains a state machine and so I transition from one bootstrapping state to another. Each states transition function starts either an AsyncTask or an IntentService and once it's done, it dispatches an Intent back to Service to let it know that the task was executed successfully. However, during that, the service just stops, and thus the intent is being dispatched into nothing, which is frustrating.
I don't want to use a Foreground Service and I don't want to trick around just to keep my service alive. I also don't want to rely on onHandleIntent() of an IntentService, since the IntentService looses all its states, meaning all members get nulled once ran through, so when stateA is finished and stateB should be kicked off, the whole statemachine is null, all previous states are gone, etc....
I commit the Services context to each IntentService/AsnycTask and I thought, as long as they hold a reference of the service context, the Service wont stop. Sadly, this is not the case...
Do I have to invoke a method on the context while doInBackground() an AsyncTask, just to keep the Service alive or something?
Beside system running out of memory, you can get your process killed if you exceed certain amount of memory with your service(check limitations).
Like with service processes, foreground processes can extend your service's lifespan, but you have no guarantees either.
I think your best shot is making a logic that will go with services in START_STICKY mode(link).
I wonder what conditions must be met so Android stops a Service, besides the obvious, running low on memory.
A service can be stopped by the user at any time for any reason, either by directly stopping the individual service, or (more likely) by terminating the whole process.
Android will stop a service individually if it crashes. More commonly, it terminates the entire process to reclaim that process' memory for other uses.
I run a bootstrapping Service, holding a local BroadcastReceiver
I doubt anyone but you knows what "bootstrapping" means in this context.
Each states transition function starts either an AsyncTask or an IntentService and once it's done, it dispatches an Intent back to Service to let it know that the task was executed successfully.
Using an AsyncTask from a Service is frequently pointless. You do not want to do stuff on the main application thread in a Service, and the point behind an AsyncTask is to do some work on the main application thread (e.g., onPostExecute()). Use a Thread.
Using an IntentService from a Service is pointless and wasteful. You already have a Service -- it's doing the "bootstrapping". You do not need another Service. Use a Thread.
However, during that, the service just stops, and thus the intent is being dispatched into nothing, which is frustrating.
More likely, the whole process is gone.
I commit the Services context to each IntentService/AsnycTask
I am not completely clear what "commit" means here, but if you are passing a Context (Service) to another Context (IntentService), that is a serious code smell.
as long as they hold a reference of the service context, the service wont stop
No. Moreover, none of that stops Android from terminating your process.
Do I have to invoke a method on the context while doInBackground() an AsyncTask, just to keep the Service alive or something?
No, you need to keep your state machine persistent (a.k.a., a file), so that if your process terminates for whatever reason, when you next run again, you can pick up from where you left off.
I'm new to Android and I've been quite confused about the life time of service and thread.
Let's say I have an activity and it starts a service in a worker thread by calling startService(). According to Google documentations, the service will run indefinitely even if the calling component is destroyed.
So here's my question:
if the application process is completely destroyed ( exited and cleaned from back stack ), is the service still running ? Is the UI thread still running as well ? If yes, does that mean the thread is not necessarily killed even if its calling process is destroyed ?
1 . Service can be stop by system when device low resource or low memory
2 . If your app is force stopped (by system task killer or some app with root permission) your service
is also destroy unless you start app again and restart your service
3 . If your app is cleaned from back stack or exited your service is not destroyed , and thread still running , any update to UI in this time can make error
Hope this info help
A Thread is not a service. A Service is generally declared in the manifest and has a lifecycle of its own. When it is not declared in a manifest, it can run beyond the lifecycle of an Activity but it will only run when started through a declared element in the manifest (i.e. an Activity or another Service).
You are using the terms without clearly making this distinction. Take a look a this:
http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html
It helps to make the distinction among "threads" and "services." As pointed out in other answers, both a Service and a thread can be destroyed when the system is low on resources. However, if a thread is created from an Activity and manages its memory properly, it will die when the Activity dies (because no references are held to it). If it keeps a reference to the Activity, it may not die, but neither will the Activity even if there is no way to return to the Activity. This is a type of memory leak and should be avoided.
Just to be clear, a Service runs independent of an Activity and has it's own thread. A java thread does also, but should not survive the lifespan of an Activity that creates it.
Service is not destroyed by itself. You need to call stopself() from the calling Activity. Even if the calling activity is destroyed it will not be destroyed. You can instead use IntentService, which are self destroying after finishing the work.
IntentService
Service
I have doubts when it comes to Services.
I know the service runs in the background, but I thought you necessarily needed to create a thread within the service, otherwise it would block the main thread and you would get an ANR error.
I thought I got it! But then I read this in the Android Developer guide:
…if your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting application performance, you should start a new thread inside the service.>
The paragraph mentions "intensive or blocking operations", but doesn’t mention an ANR error, it mentions performance. So how a service works?
Supposing an Activity starts a Service. Does the Service run by default in the background of the main thread? Meaning that you can still use your activity while the service is running, but since your Activity and the Service are sharing the main thread’s resources, it would slow down the performance of your activity, and if Service is doing CPU intensive work, it could leave no resources for the activity to use, and eventually you would get an ANR error.
The best practice (but not necessarily, if the service is doing light work) would be to start a new Thread within the Service, now the Activity and the Service are using their own thread’s resources. Then you could close your activity, but Android keeps the service thread alive.
Is that it? Thanks =)
I thought you necessarily needed to create a thread within the service, otherwise it would block the main thread and you would get an ANR error.
Correct.
The paragraph mentions "intensive or blocking operations", but doesn’t mention an ANR error, it mentions performance.
Feel free to file a bug report at http://b.android.com to get them to improve this portion of the documentation. :-)
Does the Service run by default in the background of the main thread?
The lifecycle methods of a Service, such as onCreate() and onStartCommand(), are called on the main application thread. Some services, like IntentService, will provide you with a background thread (e.g., for onHandleIntent()), but that is specific to that particular subclass of Service.
and eventually you would get an ANR error.
Yes.
The best practice (but not necessarily, if the service is doing light work) would be to start a new Thread within the Service, now the Activity and the Service are using their own thread’s resources. Then you could close your activity, but Android keeps the service thread alive.
Basically, yes. Here, "light work" should be less than a millisecond or so. Also, some things that you might do are naturally asynchronous (e.g., playing a song via MediaPlayer), so it may be that the Service itself does not need its own thread, because something else that it is using is doing the threading.
Is there any difference in running background threads from an Activity and from a Service that is started by the Activity? Added: The background threads do not interact with the UI.
I currently have some background threads that are launched from the Activity. Most are via AsyncTask and one is through my own ExecutorService. I would like to know if there is a significant benefit to refactoring the code to move these to a Service or IntentService.
You seem to be confused about the definition of Activities and Services. To make it clear:
Activities are things that run according to the Activity lifecycle state machine. The code in the respective handlers interacts with an event loop attached to a UI.
Services are things that run according to the Service lifecycle state machine. The code in the respective lifecycle handlers performs operations to handle things like Intents, etc..., but does not interact with the user via a UI.
Both of these, however, run on the "main thread" of the application. By itself, an Activity or a Service (or Broadcast Receiver, Content provider, etc...) is not a thread. Look at the documentation, and you will see that the Activity and Service classes do not, in fact, form a thread. Instead, they are hooks that will run inside the Android framework, and the framework will at the appropriate time call them on the "main" thread of the app.
You can create separate threads for the app, or use an AsyncTask to do work and publish it to the UI thread easily (something not so easily achieved with a Service).
Threads that are bound to Activities have the same lifecycle. So if you restart/kill the Activity, the thread will also be restarted/killed. This is a problem if you don't manage the lifecycle of an Activity. A service is good in this case. You can have the activity destroyed and still a worker thread running in the background (in the service). But be advised that, if the Android system need resources (memory for example) it will kill the services first (and then restart them according to their Sticky flag). In my opinion, there are no actual benefit in changing threads from the Activity to a Service, since you control the workflow of your activity. If the threads are heavy (and brake the UI for moments) consider putting them in a service on a separate process (in AndroidManifest put the process name of the service).
In Android documentation:
Caution: Another problem you might encounter when using a worker
thread is unexpected restarts in your activity due to a runtime
configuration change (such as when the user changes the screen
orientation), which may destroy your worker thread. To see how you can
persist your task during one of these restarts and how to properly
cancel the task when the activity is destroyed, see the source code
for the Shelves sample application.
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.