Somehow I am having a hard time parsing the official description of the START_STICKY flag:
Constant to return from onStartCommand(Intent, int, int): if this
service's process is killed while it is started (after returning from
onStartCommand(Intent, int, int)), then leave it in the started state
but don't retain this delivered intent. Later the system will try to
re-create the service. Because it is in the started state, it will
guarantee to call onStartCommand(Intent, int, int) after creating the
new service instance; if there are not any pending start commands to
be delivered to the service, it will be called with a null intent
object, so you must take care to check for this.
This mode makes sense for things that will be explicitly started and
stopped to run for arbitrary periods of time, such as a service
performing background music playback.
Specifically, the following four parts do not make technical sense (aka make me go WTF):
"if this service's process is killed ..., then leave it in the started state" [how do you leave something that is killed in the started state?]
"Later the system will try to re-create the service. Because it is in the started state, ..." [why is it in the started state if the system is trying to re-create the service?]
"Because it is in the started state, it will guarantee to call onStartCommand(...) ..." ["it will guarantee to call"? sorry, can't parse that phrase linguistically]
"This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, ..." ["and stopped to run"??]
Does anybody have a better spec of this flag? And, to any Googlers reading this: wtf? Can you get it fixed internally pronto?
As you know, there are two forms a service can have in Android:
Started service
Bound service
The key point to understanding the description is that a Started service must manage its own lifecycle, i.e. the ONLY components that can stop the service is the service itself by calling stopSelf() or another component by calling stopService(). Once a Started service has been started (onStartCommand() returns) it’s in a started state and it won't stop unless either stopSelf() or stopService() is called. So, if the system prematurely kills the service (neither stopSelf() or stopService() has been called), the service still is considered to be in a started state. And it’s up to you to tell (signal to) the system how to proceed with the service after killing it by returning a flag in onStartCommand().
Probably the description of the START_STICKY flag given at the end of Extending the Service class will be more clear for you.
P.S. Regarding the "and stopped to run??" confusion, try reading it as "...explicitly started and stopped in order to run..."
EDIT:
Also take a look at this question.
START_STICKY and START_NOT_STICKY
START_STICKY tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent
Related
I am working on an android app to play music.
So far I have returned START_STICKY from the onStartCommand of the Service responsible for playing the music without much thought becuase the tooltip in Eclipse states: "This mode makes sense for [...] a service performing background music playback".
The first thing this method does is looking in the intent what it is supposed to do (play, stop, next song, ...).
Recently when I killed the app while playing music (by dragging it out of the screen in the overview of recent apps) the app crashed. Looking in the log file I found that a NullPointerException was thrown when trying to access the intent in onStartCommand (after the Apllications's and Service's onCreate methods had been called).
My first reflex was to therefore insert at the beginning of the onStartCommand method:
if (intent == null){
stopSelf();
return START_NOT_STICKY;
}
But after reading the descriptions of START_STICKY and START_NOT_STICKY again I am wondering: Why would START_STICKY be recommended for a music player?
The way I understand it is that the difference between the two is that if a service started with START_STICKY is killed it will be restarted (then with intent=null). With START_NOT_STICKY the service will not be restarted (unless the user requests it), therefore it will always be called with an intent and I would not need to check whether it is null or not.
When the user kills the app it seems obvious to me that the service should not be restarted.
The other case I can think of where the service might be restarted is if the service had been killed by the system due to a lack of ressources. In that case, too, I don't think a user would want the music to unexpectedly start playing music just becuase some ressources became available.
The following two answers imply that the return code has no other meaning than whether the service should be restarted if the process was killed:
What is START_STICKY,START_NOT_STICKY and START_REDELIVER_INTENT
Service
START_STICKY and START_NOT_STICKY
Why is START_STICKY recommended for a music player?
START_STICKY- If the service is stopped due to low memory then service is recreated 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- If the service is stopped the system not to bother to restart the service, even when it has sufficient memory.
Also when user kills the app the service wont be stopped unless you stop the process by using some task killers.For more info on service check this link.
http://www.vogella.com/tutorials/AndroidServices/article.html
int START_STICKY:
Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service. Because it is in the started state, it will guarantee to call onStartCommand(Intent, int, int) after creating the new service instance; if there are not any pending start commands to be delivered to the service, it will be called with a null intent object, so you must take care to check for this.This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.
so it is self-exolanatory refer this STICKY SERVICE
About using START_STICKY in Android Service.
official document says:
if this service's process is killed while it is started (after
returning from onStartCommand(Intent, int, int)), then leave it in the
started state but don't retain this delivered intent. Later the system
will try to re-create the service. Because it is in the started state,
it will guarantee to call onStartCommand(Intent, int, int) after
creating the new service instance;
This is understandable, so when an started service's process is killed due to lack of memory, the OS will automatically try to start the service again later.
My question is, if my code starts the service startService(...), and later stop it(e.g. I have a "STOP" button on my app's UI, when press it, I call stopService(...)), will system later start the service again? Or will the service instance be cleared from memory completely without later being created by system? (No service binding for this scenario)
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.
And answer for your query is the service only recreate if it's killed by the OS in any circumstances when working with START_STICKY. if we were terminating the service why android need to reproduce it again.if your using stopSelf() the service does not recreate even it is sticky.
I have had that stopService() button in my app during testing. Once you stop it using the command, it will not start again until you call startService().
Android kill the process from time to time. However Sticky service is recreated automatically by android system. Somebody told, Sticky services are destroyed and are recreated after 5 seconds.
START_STICKY is the operation mode of the started services, depending on the value they return from on StartCommand() method.START_STICKY is used for services that create the copy of service but it won`t store any result of services which is performed before.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logs.d(TAG, "# Service - onStartCommand() starts here");
// If service returns START_STICKY, android restarts service automatically after forced close.
// At this time, onStartCommand() method in service must handle null intent.
return Service.START_STICKY;
}
I have a Service running in the foreground, and an Activity that interacts with it. If the Activity crashes, Android kills the entire process, including the foreground Service and its associated Threads.
However, the ongoing notification provided by the Service does not go away, and upon closer inspection, Android's task manager reveals that the Service itself is still running.
How can I kill the foreground Service in this circumstance?
Have you override onStartCommand method of the Service? What value is it returning? If not, try to override it and return START_NOT_STICKY from it.
START_STICKY: If this service's process is killed while it is started, then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service.
START_NOT_STICKY: If this service's process is killed while it is started, and there are no new start intents to deliver to it, then take the service out of the started state and don't recreate.
Not sure, as I have never worked on foreground services, but this might be the reason.
Are you sure the service is not running it its own process...
Also can you confirm whether the service is getting restarted..If its getting restarted-it is because you are returning START_STICKY from onStartCommand()
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.
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