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
Related
I want my FusedLocationProvider to ping for location even when the screen is off. For this, in my service, I have a PARTIAL_WAKE_LOCK, to keep the CPU running and to ensure that the service continues to run even when the screen is off.
That being said, I know the Android OS will kill off services/apps in the background when it needs memory. Due to this, my service can be killed off.
When this happens, onDestroy() in the Service is not guaranteed to be called. If that is the case, how do I ensure that the WakeLock gets released?
I call mWakeLock.acquire(); in onStartCommand, and in onDestroy I call mWakeLock.release();
how do I ensure that the WakeLock gets released?
According to the docs:
If the service is currently executing code in its onCreate(),
onStartCommand(), or onDestroy() methods, then the hosting process will be a
foreground process to ensure this code can execute without being killed.
What this means is that if the code in any of those methods is currently being executed, then the process won't be killed (or at least will be given a very high priority) till the code finishes executing.
However, the short answer to your question is that there is NO way to ensure that onDestroy() or onPause() gets called. onPause(), though, does have a far greater probability of getting called, so you could look into that. There is also a method, Application.onTerminate() which you may want to use for further research on this. The method is only called when running the app on emulators.
I don't think you need to worry about a memory leak, though (assuming that we are both on the same page regarding what such a leak constitutes). When a process is killed, the memory is reclaimed by the kernel, not by the GC, so there isn't going to be a memory leak in that case.
EDIT:
I have confirmed that if a process is killed, an acquired wakelock will necessarily be released:
1. Does the android os release a wakelock if the app or service holding it is killed ?.
2. What happens with the partial wake lock if the process that acquires is killed ?.
3. Binders & Death Recipients.
4. How to deal with (orphaned) WakeLocks?.
I am unable to understand
START_STICKY,
START_NOT_STICKY and
START_REDELIVER_INTENT
Can anyone explain clearly with examples.
I went through this link but couldn't understand it clearly.
These are related to services. We all know that services keeps on running in the background and they also consume some memory to execute.
So, as more of the application runs on android device, the device memory keeps on getting low and when the time arises, when the device memory gets critically low, the android system starts terminating processes, so as to release the memory occupied by the processes.
But you might be doing some important task with the services, that could also get terminated as the service stops. so these concepts are to tell the android system what action you want to perform when the device memory gets stable and when it is ready to relaunch the services.
The simplest explanation of these could be,
START_STICKY- tells the system to create a fresh copy of the service, when sufficient memory is available, after it recovers from low memory. Here you will lose the results that might have computed before.
START_NOT_STICKY- tells the system not to bother to restart the service, even when it has sufficient memory.
START_REDELIVER_INTENT- tells the system to restart the service after the crash and also redeliver the intents that were present at the time of crash.
Well, I read the thread in your link, and it says it all.
if your service is killed by Android due to low memory, and Android clears some memory, then...
STICKY: ...Android will restart your service, because that particular flag is set.
NOT_STICKY: ...Android will not care about starting again, because the flag tells Android it shouldn't bother.
REDELIVER_INTENT: ...Android will restart the service AND redeliver the same intent to onStartCommand() of the service, because, again, of the flag.
Both codes are only relevant when the phone runs out of memory and kills the service before it finishes executing. START_STICKY tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent. START_NOT_STICKY tells the OS to not bother recreating the service again. There is also a third code START_REDELIVER_INTENT that tells the OS to recreate the service AND redelivery the same intent to onStartCommand().
This article by Dianne Hackborn explained the background of this a lot better then the official documentation.
Source: http://android-developers.blogspot.com.au/2010/02/service-api-changes-starting-with.html
The key part here is a new result code returned by the function, telling the system what it should do with the service if its process is killed while it is running:
START_STICKY is basically the same as the previous behavior, where the
service is left "started" and will later be restarted by the system.
The only difference from previous versions of the platform is that it
if it gets restarted because its process is killed, onStartCommand()
will be called on the next instance of the service with a null Intent
instead of not being called at all. Services that use this mode should
always check for this case and deal with it appropriately.
START_NOT_STICKY says that, after returning from onStartCreated(), if
the process is killed with no remaining start commands to deliver,
then the service will be stopped instead of restarted. This makes a
lot more sense for services that are intended to only run while
executing commands sent to them. For example, a service may be started
every 15 minutes from an alarm to poll some network state. If it gets
killed while doing that work, it would be best to just let it be
stopped and get started the next time the alarm fires.
START_REDELIVER_INTENT is like START_NOT_STICKY, except if the
service's process is killed before it calls stopSelf() for a given
intent, that intent will be re-delivered to it until it completes
(unless after some number of more tries it still can't complete, at
which point the system gives up). This is useful for services that are
receiving commands of work to do, and want to make sure they do
eventually complete the work for each command sent.
I am aware that force killing an app is very bad, but the client requires it. I am required to implement a force reboot of sorts for the app. This is how I implemented it:
I create a BroadcastReceiver in my Application's (not Activity's) onCreate method. I have it wait for the REBOOT command to be broadcast. Upon receipt, I have it broadcast another message that has the services call stopSelf so that threads and services have a chance to exit cleanly. I then have an AlarmManager call my main activity 5 seconds later. Finally have my application kill itself with Process.kill(Process.myPid()). For the most part, it works, and I just need to add some extra waiting time before it kills the process (maybe by waiting for a TERMINATE broadcast from each running Service). My issue is this: while reviewing the logs, I found out that the system schedules the services to reboot. I'm worried about conflicts. Is there a way to terminate the services without any chance of it rebooting?
I fixed this by having the Receiver wait for all the services to finish their onDestroy() calls before having it die. I also changed from Process.kill() to ActivityManager.killBackgroundProcesses().
As a side note: I know it's wrong, but it really does feel cool killing the processes hehehe.
What happens to a service started by BOOT_COMPLETE after system kills it for memory?
Will it ever be restarted without rebooting the phone? Is it possible to restart it somehow?
What is the best practice to avoid as much as possible an important service from being killed?
Will it ever be restarted without rebooting the phone?
Possibly. If it truly was because "system kills it for memory", and you return an appropriate value from onStartCommand() (e.g., START_STICKY), it should be restarted at some point in the future. If the service was killed due to user action (e.g., Force Stop in the Manage Services screen in Settings), it will not be restarted.
What is the best practice to avoid as much as possible an important service from being killed?
First, design your application to not rely on an everlasting service like this. 99.44% of Android applications do not need a service that runs continuously, let alone one that starts doing so at boot time. Android device users hate developers who think that their apps are sooooooooooooo important that they have services running all the time -- that's why we have task killers, Force Stop, and Android killing services due to old age. For example, if you are checking for new email every 15 minutes, use AlarmManager and an IntentService, not a service that runs forever.
If you can demonstrate -- to me and to your users -- that yours is among the 0.56% of applications that really do need a service that starts at boot time and runs forever, you can use startForeground(). This will indicate to the OS that your service is part of the foreground user experience. You will have to display a Notification, ideally to allow the user to shut down your service cleanly if and when the user no longer feels that it is justified.
If you need to restart the service then you should use AlarmManager to check up on the service in a separate BroadcastReceiver, but nominally when a service is killed by the system for memory it will not get automatically restarted.
You may want to take a look at START_STICKY
Use the AlarmManager to periodically send an Intent-- receive the intent and make sure your service is running.
What happens to android application and activities and services that belongs to application when the phone/AP goes to sleep mode?Will the framework destroy Activities and Services and OS kills the process?
In case of device sleep, activity's `onPause()' will be called. Read activity lifecycle to understand this.
OS only kills the process when memory/resources are low. Activities are killed first, services are only killed as last resort.
But there is no guarantee they will not be killed. This is why you should rely on system services to call you when you need some work done: use AlarmManager to do call your code periodically or use listeners to notify you of system changes (gps, network, etc..)
When the phone sleeps activities don't get destroyed. I believe all that happens is the activities stay the same but fire the onPause() method.
See this image:
What i saw in my application is that only the onPause() method of the main activity (category.LAUNCHER) is called. This happened when the phone went to sleep and before that the main activity of the application had been started.
When any one of the other activities had been started before the phone was going to sleep the first onPause() is called then onStop() and in the end onDestroy() - this is for activities which are category.DEFAULT into the manifest.
I don't know maybe the problem is in my code?
When the phone goes to sleep the onPause() method is called. This method is just a warning to your app. Then depending on the device the CPU may also go to sleep and execution of your code may stop. On most devices this may be anywhere from 10 to 60 seconds after the screen goes black.
It is very unlikely that going to sleep will result in your app being killed.