confusion about Android service and thread - android

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

Related

How is a running IntentService managed after the app process is killed

Just trying to clarify my understanding of how an IntentService is managed by the OS once terminating states have been reached. By terminating, I mean when the current activity is destroyed or the app process is killed, as per the following documentation:
https://developer.android.com/guide/components/activities/activity-lifecycle
Given the comment
Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask
at https://developer.android.com/training/run-background-service/create-service;
I feel as if:
1) A started IntentService is unaffected by the activity lifecycle. Is this correct?
2) If (1) is true, will it continue to run indefinitely even after a terminating state is reached, up to some point that it either stops itself or the OS decides to stop it?
In my particular situation, I'm using an IntentService during app startup to query APIs, grab content, and then add a new (landing) Page to the Xamarin.Forms navigation stack (this would be equivalent to starting a new activity).
This leads me to my next question...
3) What happens if the app is already in a terminated state when it comes time to the IntentService creating a new Activity? Surely the Activity can't be added to the navigation stack as it no longer exists once the app is terminated?
Yes, a started IntentService is unaffected by the Activity Lifecycle. Actually, all Services outside of bound Services are unaffected by the Activity Lifecycle.
An IntentService will continue until it reaches completion of it's work, the application is destroyed, or if the System decides to kill the Service due to the changes in the Android 8.0 background Service rules.
Your use of terminated state is too broad... If the Application is already terminated, then nothing will happen because the IntentService would have been terminated already too. If it's the Activity that launched the IntentService that was terminated, then nothing happens, since by default, an IntentService has nothing to do with Activities, even if it's the one that started it.
For the last question, it really depends on how you choose to communicate the result of IntentService to an Activity.
If you're using a BroadcastReceiver, then nothing will happen because an IntentService will fire the broadcast without any problems, but the Activity won't be able to receive the results since it's terminated.
But if you're simply creating a new Activity, then you can simply use startActivity() with the result data added to the Intent. Though, I doubt the user will be happy to see an Activity suddenly open on the screen when they're no longer in your app. Starting a new Activity has nothing to do with a previous Activity, since any instance of a Context can start an Activity.
Honestly, based on your question, it sounds like you're very concerned with an IntentService and it's connection with the Activity that started it. If that's the case, you really shouldn't be using an IntentService, since that's not really it's purpose. It's not meant to have a connection with an Activity. It's simply meant to do work and finish.
Instead, a bound Service would be a better option since it has a direct connection with the Activity that started it.

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).

Long running operation inside onEvent of FileObserver

I have an activity that contains an Instance of FileObserver. I start watching in onCreate and stop watching in onDestroy of the activity. So what happens if onEvent is doing some operation and the activity is destroyed (user presses back button)? Does my onEvent continue to finish what it was doing? Basically I am wondering whether onEvent should start a service or handle its business itself.
Does my onEvent continue to finish what it was doing?
At least briefly, yes. FileObserver is not tied to a specific component's lifecycle, like that of an Activity.
However, once your app is no longer in the foreground, your process can be terminated at any point, to free up system RAM for other apps. Android is not going to pay any attention to your FileObserver and its onEvent() processing when this occurs, by default.
If you expect the work to happen quickly — say, under a second — you should be able to keep it where it is.
If, however, the sort of work that you are doing is more substantial, I would consider having a service do the work. Per our prior discussion, while the FileObserver should not be in an IntentService, the work triggered by the FileObserver could be. onEvent() would call startService() to tell the service to go do the work. Services are a signal to the OS that you are actively doing work on behalf of the user, and so your process is more likely to hang around for a bit longer.
Unless the Application is stopped the code in your onEvent will continue to run.
FileObserver.onEvent documentation
This method is invoked on a special FileObserver thread. It runs independently of any threads, so take care to use appropriate synchronization! Consider using post(Runnable) to shift event handling work to the main thread to avoid concurrency problems.
So the only think you need to be concerned with is what exactly you are doing in onEvent. For instance if you are updating UI or interacting with the Activity / Fragment in your onEvent method then this could cause a crash if the Activity goes away.
With that in mind a service will certainly increase the odds that the application does not terminate while you are performing your work.
Service documentation
The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed. Otherwise, if the service was started and is long-running, then the system will lower its position in the list of background tasks over time and the service will become highly susceptible to killing—if your service is started, then you must design it to gracefully handle restarts by the system. If the system kills your service, it restarts it as soon as resources become available again...
So the bottom line is that a service is more likely to keep your application alive. Event more likely if you call startForeground but in this case you need to be willing to show a notification to the user.

Why is my Service stopping?

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.

When I close the Activity the service is killed then started again

I have a simple android program containing one activity and one service.
I am starting the service from the activity by calling: startService()
The service should continue running when I close my activity as I started it by calling startService. What I am noticing is that when I close the activity the service is killed then started again after short time.
Is that a normal behavior in android?
If it is normal, is there any way to enforce keeping the exact service running?
Thank you very much
Rami
How are you "closing" the Activity? There's no need to kill an Activity once you're finished using it, and the Service should keep running even if your Activity is in the background.
Service.onDestroy() is called before the system destroys your Service. However, I am inclined to believe that you have a different problem, since it's unusual for a Service to be killed unless your device is very low on memory.

Categories

Resources