I'm writing an app which has a long-running service.
I've written some state-saving code in the service's onDestroy method.
My intention is that this should be invoked if the service ever gets killed by Android, due to memory pressure.
How can I simulate the service being killed by memory pressure?
I've tried adb shell am force-stop com.example.app but the service's onDestroy method was not invoked.
Is onDestroy a sensible site for service-shutdown-state-saving?
If so, how can I make a service's onDestroy be invoked by Android, for debugging/testing purposes?
You should not rely on onDestroy() because it only gets called, when service is properly stopped (by calling stopService() or stopSelf() method).
If you want to save service state, you should either save it as you go (for instance a player service can store it when play/pause function is activated), or use a timer to save it periodically.
If you want to react to memory events, you should use ComponentCallbacks2 class, which will notify you, when Android needs more memory. If you free memory inside those callbacks, you will increase probability your service will stay in memory longer.
Hope this helps.
If you want to programmatically stop your Service, within the Service, call stopSelf().
Alternatively go to the app settings and do a force stop.
A force stop will not call onDestroy on any components, neither service nor activity. It completely closes the app without any further considerations.
I'm not sure about this but if your service isn't running as foreground service you can close it by removing the app from recent apps menu.
Related
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.
I have a doubt that if i start a periodic service using alarm manager and start the service from the onCreate method of an activity. How can i prevent the service from triggering multiple times if that activity is launched again and again.
Assuming that you are creating a Normal Service (and not an IntentService), as per the Android Service documentation, when app invokes startService call, service will be instantiated and started (creating a process for it if needed).
Also, if it is running then it remains running.
So, to put it in simple terms,
Life cycle of "Started" service is independent of the life cycle of
Activity which has started this service. This is true irrespective
weather both are running in same process or different processes
So even though your Activity may be getting created multiple times, and if Service you created earlier is still running, then service object that already exists will be reused.
However, if there is a call to startService() from onCreate() of an Activity, this will invoke each time onStartCommand().
Hence, you need to ensure that you have a appropriate code/logic to handle multiple invocations of onStartCommand()
As far as I understood you must do something in either onCreate/onStart and onStop or onResume and onPaused. By do something I mean, in onCreate create what you need, alarm manager, etc then in onStart you can start the service and in onStop you stop the service or unBind from it, in case you want a foreground service. or in onResume or onStop.
Take a look here:
https://github.com/toaderandrei/live_tracking/blob/master/app/src/main/java/com/ant/track/activities/ServiceConnectActivity.java.
It is a tracking app that is based on MyTracks app from google.
I have a long running service which responds to multiple BroadcastReceivers (created in code, not manifest). Most of the time the service is running well, but from time to time it gets somehow stopped (the BroadcastReceivers stop to work) - I guess the system pauses it somehow (when I look into the running processes on the device I can clearly see the service is still "runnning").
I don't know the right reason why the service is being paused, but I'd like to know whether in these cases the onDestroy() method is called or whether there's a chance to handle this somehow.
I presume onDestroy() is not being called, because the service is still visible in the Running processes tab. I also have the service return the START_STICKY flag so the system should restart it whenever it's killed for memory reasons. Also if it is "paused" somehow, is it possible to create a WakeLock for this not to occur?
I know that the best solution would be to put all the BroadcastReceivers into the manifest and create a one shot-service called from their onReceive() methods. However I have chosen to go with the way of long running service because the initialization stage is very intensive it's better to initialize everything just once.
onDestroy() will be called only when service is being killed by lack of resources or when you explicitly stop it.
The service can be "paused" when your phone goes idle (usually when screen is off) because the CPU stops. To make services run always you should use PowerManager.PARTIAL_WAKE_LOCK - but use it wisely because it does not stop your CPU and thus draining the battery. You should never leave your apps running always. Just do what you need holding a WakeLock and then release it.
http://developer.android.com/reference/android/os/PowerManager.html
http://developer.android.com/reference/android/os/PowerManager.WakeLock.html
You can use AlarmManager to "wake" your apps periodically and do something.
http://developer.android.com/reference/android/app/AlarmManager.html
From my little android knowledge I understand that android OS can kill my service under extreme memory conditions.
I have created a service that returns START_STICKY. The service is meant to run in background.
If android is about to kill my service, will it call onDestroy ?
And when it restarts it would it call onCreate ?
See here, the dev guide. http://developer.android.com/reference/android/app/Service.html#ProcessLifecycle
onCreate() is only called when the process starts, which can either be the first time the service is running, or if it was killed on restarted, essentially this is called whenever it starts.
onStartCommand() is called whenever a client calls startService().
When a service is destroyed / completely stopped, Android is supposed to call onDestroy() on that service. I think it's possible for that to not happen (e.g. process is killed not through Android system). In the case of a bound service, this is when there are not more active client binders.
Edit: onCreate() Service starts; onStartCommand()someone uses service; onDestroy()Service is killed / stopped.
If someone calls Context.startService() then the system will retrieve
the service (creating it and calling its onCreate() method if needed)
and then call its onStartCommand(Intent, int, int) method with the
arguments supplied by the client
...
A service can be both started and have connections bound to it. In
such a case, the system will keep the service running as long as
either it is started or there are one or more connections to it with
the Context.BIND_AUTO_CREATE flag. Once neither of these situations
hold, the service's onDestroy() method is called and the service is
effectively terminated. All cleanup (stopping threads, unregistering
receivers) should be complete upon returning from onDestroy().
http://developer.android.com/reference/android/app/Service.html
EDIT: Quick answer. Yes to both questions
My android application starts a service in the onCreate() callback of a class that extends Application. The service performs some background tasks that are relevant to the user only while the application is running. For that reason I would like to close the service when the application's last activity is closed. I've tried to perform closing the service in the callback onTerminate() , but it never gets called . So what would be the best place where a service should be closed ?
Thanks !
An Android service, once started, will continue running until the Context.stopService() or stopSelf() is called.
There are various hooks you can use to stop the service using Context.stopService (the service itself, or an onDestroy()/onPause callback in one of the activities, or a button click).
It's true that Android does some resource management itself, but it can take a long time before Android decides to terminate your services. And a service that's running but not doing anything just consumes resources on the phone that other apps might need.
In your case, the onPause method of your last activity would be a good that will get called, and as such is the correct place to stop the service.
The onPause() callback will be made when your activity is paused for any reason, and you know that when this happens your app will not be visible again until onResume() is called. If your service has a reason to run in the use case that your activity might be started again soon, you should add an entry to your service that onPause() calls, to set a delayed service termination. In onResume() you can cancel that delayed termination through another entry.