I would like to issue broadcast when service goes down. What callback is guaranteed to run when this happens? I want other apps to know its down, I cannot take a chance that it goes down and no one knows about it. So at point in the service lifecycle (which method) should I issue the sendBroadcast(ImGoingDown)? For example, how soon would onDestroy() be called?
While most answers here are aiding in the onDestroy approach, there are many events on your service being destroyed that you cannot intervene. For instance, if the user has force closed your application, your service is destroyed, but onDestroy will NOT be executed.
On a common scenario, your service would be destroyed when it has ran out of operations (mostly know as finished), when no other process that are bound to the service, or when its stopSelf()is executed, and most common, when the device is running low on RAM.
onDestroy would be the scenario where you can restart it.
As a suggestion, if the device has killed your process due to low RAM, dont restart it right away. set a Handler or AlarmManager to start it a bit later (so the lack of memmomry dont execute in back again.)
You can fire the broadcast in onDestroy(). This is the last call the service receives before getting destroyed. Service lifecycle ends with this call.
If you are running a background service that means you must be doing something in background, sending broadcast from onDestroy() might not be a best practice.
Think, your service gets destroyed because the task you wanted to run is completed, then you might don't want to send a broadcast in that case. You want to send a broadcast only when the service is killed right? So the better approach is to setting a boolean, say isTaskFinised, and if it returns false only then your onDestroy() should send a broadcast.
#Override
public void onDestroy(){
if(!isTaskFinished){
//send a broadcast
}
}
Related
I am looking for a bit of app design advice.
I have an app that connects to the Google Location Services and tracks location coordinates it receives. These are displayed as a path on the UI.
When the screen times out and goes blank then this Activity will, of course, shut down as per the normal Activity life cycle.
However - I atill want to record the co-ordinates coming back in each onLocationChanged event from Location Services, but, of course, the Activity has paused so it cannot do that.
I don't particularly want to prevent the screen from blanking in the Manifest (and thus the Activity would never pause). Though I believe it would still pause if, say, a phone call is received etc.
My solution would be to start an IntentService in one of the Activity pausing events (either onPause, onStop or onSaveInstanceState) to receive Location updates, and then when the Activity restarts, collect the data from the Service and close the Service down.
Would this be an efficient and correct way of achieving this, or is there some Android black art that I don't know about? If so, is IntentService the correct way to go about it (or should I use Service)?
Proberly a normal service that gets restarted by an alarmmanager is an better idea.
In order to tie up loose ends, I'll add my own answer to this now I have implemented something.
My solution in the end was not an IntentService. This was because I thought that the IntentService would consider its work to be the actual setting up of the LocationService and once that work had been completed then it would shut itself down rather than hang about waiting for LocationService 'pings'.
Therefore, I implemented a normal Service, but I bound it to the calling Activity. I also set up a callback to the Activity. This way when a 'ping' was received I could process it and pass back the data directly to the Activity. Also, the Service would remain alive as long as the binding was in place. I clear the binder when the Activity is destroyed.
This worked perfectly....HOWEVER
I then discovered that the reason that the LocationService 'pings' were not being handled in the Activity was bacause I was disconnecting the GoogleAPIClient when the Activity onStop was called. Having removed this, the Activity processed the 'pings'even in its stopped state, so no Service was required anyway.
Therefore the correct answer to this question is... Activity should continue processing in the background (unless it's destroyed for memory management purposes), so check you're not stopping stuff in your 'shutdown' handlers onPause onStop etc. Then you won't waste time writing services like I did!
Say I have an Activity that launches a Service using startService() when user presses a button. The service is stopped using another intent in startService() when user presses another button, or it can decide to stop itself. The service wants to run forever, so it returns START_STICKY from onStartCommand(). While the service is running, it connects to some server and receives messages. Activity binds to it and, when bound, displays those messages.
Now, when the Activity is started after an OOM kill, it doesn't know if the Service is started. One can use a static field set in onStartCommand() to tell if the Service is running, but that's prone to backfire sooner or later. Moreover, the Service can be started by the system after the activity has been launched, so using a static field is not an option at all.
The cleanest solution I can come up with is using SharedPreferences to store the state of the service. This is going to fail to be good when the service is killed between SharedPreferences.setBoolean("running", false) and stopSelf(), but such a thing will probably occur rarely.
Also I can try to bind to the Service at all times. This would be very ugly but still not impossible.
Any other solutions? Maybe the very idea is wrong in some way?
I've got a Service, that starting with BOOT_COMPLETED. This Service periodicaly sends GPS data to the server. Sometimes OS kills this Service in the wake of memory, but onDestroy() method of Service didn't called. Where can i put some values for saving and restoring when my Service is restarted?
Simple put: You can't with the regular service lifecycle events.
If the onDestroy() method is not called the system killed the process the hard way, without terminating it properly. As there is no event for that you have to use other callbacks to detect a possible kill situation.
The only possibility which could help is to listen to onTrimMemeroy or onLowMemeroy although these callbacks do not mean that your service will be killed it might help as an indicator when you should save your data.
More can be found here: http://developer.android.com/reference/android/content/ComponentCallbacks2.html
For reference, here is the lifecycle of a service if terminated properly:
You can ovveride the onTrimMemeroy() and onLowMemeroy() method to handle this problem, the detailed illustration about these two method that you can get from here
I've got some methods in onDestroy in my service. They must be called to set some application settings. Maybe there is a possibility to receive some kind of broadcast to set the settings values? As I understand, this service won't be active after the system reboots. Any ideas?
I've got some methods in onDestroy in my service
onDestroy() is not guaranteed to be called on a service. For example, if the user force-stops you from Settings, or you crash with an exception, or Android needs RAM in a hurry and terminates your process, onDestroy() is not called.
They must be called to set some application settings.
Then you should be calling them sometime other than onDestroy().
Maby there is a possibility to recive some kind of broadcast and even set the settings values?
You can try having your service listen for the ACTION_SHUTDOWN broadcast, but that will not solve your problem, as there are other scenarios in which onDestroy() will not be called, as noted above.
As I anderstand, this service when the system reboot won't be active
Correct.
I'm trying to write a Service which sits and waits for SMS messages (using a BroadcastReceiver which the server registers) and will take some action depending on the details of the SMS message. I use an Activity to startService() and stopService() for the Service. After I close the Activity, the Service continues to sit there with its state kept and its BroadcastReceiver waiting, as it should... However, I find that over time, randomly, the Service will restart itself. That is, onCreate() and onStartCommand() will be called even when the Service has already been started. This happens sometimes when my phone sits idle overnight...
Can anyone provide insight on why this is (phone requests resources and kills a service?), what I can do to prevent it, or what I can do to prevent the state of the service from being lost?
Thanks in advance.
I don't think you need to start service from activity at all. Have a broadcast receiver that listens to your SMS messages and starts the service. After work is done, service should call stopSelf();
I'll try Service.startForeground()
Android sometimes (when it's low on resources, mem/cpu) removes running services and once it's high on resources again brings them back. This is why you see that your services has been restarted a couple of times during night.