I have an app with a main Activity. I add data into a list in a service using a binder. At the same time, I start the service which runs in the background. When I close and restart the app, my list of data in the service is destroyed. Why does this happen?
Perhaps your service was killed and if You used START_STICKY it was just restarted without any parameters (as standalone service). I think you should somehow persist information that service was invoked with parameter and save it e.g. to the database. When service finishes dealing with your data, delete that information and allow it to be invoked once again.
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.
When you bind to a Service, the lifecycle of the Service is depending on the one that does the bind (in your case the Activity). So if you do a unbind in onPause/onStop the Service will be destroyed.
If you start the Service using START_STICKY it will be alive until stopped by user in code or by Android OS (when it needs resources.
(Depending what you really need), I would suggest is store it in SharedPreferences or in an other way (e.g. SQLite DB). To prevent losing data when something kills or stops the Service.
Normally your service is not destroyed every time, but if other application needs more resources and device doesn't have it, OS can stop you app.
Related
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 have a Service which handles downloading a list of simple files which it receives via the intent upon creation. I stop the Service once all the items have been downloaded. However if the System decides to kill the Service, upon recreation (because of START_STICKY) I will receive a null intent (http://developer.android.com/guide/components/services.html#START_STICKY). Is there a way to continue on where the Service was stopped without having to manually persist the list.
You could use the flag START_REDELIVER_INTENT, which will call again the onStartCommand method of the service with the last sent intent if the service's process is killed before it calls stopSelf. Anyway I don't know how and what your service exactly does, so it could be that you still have to save in a persistent way some information.
Suppose that Activity A starts Service S and binds to Service S.
What will happen to S when A is destroyed?
How can I recreate another Activity that binds to S? The sample code in http://developer.android.com/guide/components/bound-services.html unbind the service in onStop(). I think if I open the app again, a new process is created for another instance of A and S. But I want the new activity to get data from the old service.
What will happen to S when A is destroyed?
If A is the only Activity bound to S and you didn't start the Service via startService(Intent), S will be destroyed. That's because a Service will be alive till the last bound Activity unbounds from the Service. This is documented here.
How can I recreate another Activity that binds to S?
If A is bound and you switch to Activity B via Intent, the Service will be destroyed and recreated when B binds to it.
If you want the Service to be alive even if no Activity is bound to it, you have to call the Servie with startService(Intent). Now it will be around if you explicitly stop it or system means it's time to destroy it. If you don't want this behavior, persist your data and access it at given time.
I think if I open the app again, a new process is created for another instance of A and S
The process remains the same till the process is killed from the system or if you kill the process, which is not recommanded.
Edit:
Only the bound service lifecycle depends on Activities. If you want a stand alone one use startService(). This way it's independent from Activities and runs in background as long as the process of the App is up or you explicitly stop the Service with stopService() / stopSelf(). You could even have a Service in a own App and use IPC to communicate between Apps. It's all a matter of the use case.
As you can see the configuration of a Service is very flexible and you have to decide which fits best for your App.
If You start service through startService() it will keep remaining after Activity finishes.
If You start service through bindService() it will live until last Activity unbounds from it.
Also if service is already started and you call startService() no new instance of service will be created, but in living service method onStartCommand() will be executed.
Almost same when you bind to living service, methon onBind() will be executed.
I am developing an Android data entry app that saves the entered data to a file. A Service (let's call it FileIOService) is launched using the filename, and loads and saves data that is passed to it from each Activity that the user accesses.
I am trying to make the whole app as robust as possible, and at the moment I feel I need to pay particular attention to the interaction between each Activity and the Service. Here are the issues I can see:
If the Service is killed by the system, it needs to restart and open the file that it had open: I can handle this by using START_REDELIVER_INTENT.
If an Activity is destroyed, for instance by an orientation change, it needs to reconnect to the Service.
The thing is, once the Activity launches the Service, there's a while before the Service finishes opening the file and becomes ready for I/O requests. To address this, in my Activity, I have both:
an inner class subclassing ServiceConnection, with its onServiceConnected() method completed
a private reference to an anonymous inner subclass of BroadcastReceiver, with its handleMessage() method completed. This gets called when the Service sends out a broadcast to indicate it's finished opening its file.
Both of these methods then call a setUpActivity() method that pulls data from the Service. This is where it starts to get ugly. Because onServiceConnected() may run before the file is ready for I/O, and handleMessage() might be called while the Service is not bound to the Activity, I have to make both handleMessage() and onServiceConnected() set boolean flags that can later be checked in setUpActivity(), like this:
if ((fileLoaded && serviceConnected))
{
//access the file data
}
As I said, this feels ugly and awkward, and relies on setting extra boolean variables.
There's another problem - if my Activity launches an external Activity, like the Camera app, upon returning to my app the Service and Activity may both have been destroyed (especially with an orientation change) and the app crashes.
My feeling is that I may be missing some overall pattern that would define how each Activity should relate to the Service, and vice versa, while remaining robust and able to cope with unexpected terminations/restarts.
Let's ignore the fact that I am skeptical that this is a valid use case for a service (a service whose existence is simply to read and write files?).
If the Service is killed by the system, it needs to restart and open the file that it had open: I can handle this by using START_REDELIVER_INTENT.
The service is not "killed by the system". The process is killed by the system. This will eradicate your activities as well as your service.
The one possible exception to this is if the user manually stops the service (and only the service) from Settings, in which case I have no clue what the expected behavior would be. This should be fairly uncommon nowadays, particularly for an app that the user had just been using. Users will be more inclined to use a task manager, such as swiping your app off the recent-tasks list, which will get rid of the entire process, not just the service.
If an Activity is destroyed, for instance by an orientation change, it needs to reconnect to the Service.
Not necessarily:
Bind using the Application context (getApplicationContext()) instead of from the Activity directly
Use a retained fragment to maintain the binding across the configuration change
My feeling is that I may be missing some overall pattern that would define how each Activity should relate to the Service, and vice versa, while remaining robust and able to cope with unexpected terminations/restarts.
This is one of the many reasons why I try to avoid the binding pattern altogether. Use a service for processing commands, sent via startService(), with results (if any) delivered by LocalBroadcastManager, or Otto, or greenrobot's EventBus, or a "real" broadcast Intent, or maybe a Messenger. Particularly when the service is an IntentService, the service nicely cleans up after itself when there is no more work to be done.
I have an Android app, in which Activities fire long running operations that run in the background. These operations interact with the Activities when done. I'm developing a component that handles the Activity/Long-Running-Task coupling, taking care of activities being destroyed and recreated.
Right now that component is implemented as an Android service. The activities call bindService and use the resulting IBinder to start and track tasks. I decided against using startService, because I prefer the richer API possible through a Java interface.
Now the problem. Activity A start ups, binds to the service and calls serviceApi.runTask(...). Activity A is then destroyed (because the user flips the phone, for instance) and recreated as Activity A'. A' then binds again to the service, announces its existence and everything should be running nicely.
Except that my Service gets destroyed. When Activity A is destroyed, it unbinds from the service. Android sees there are no more clients, and kills the service. When Activity A' is created, the service is created again, and I lose everything the old service had.
The only solution I can see is using a singleton for the service. And then it doesn't really have to be an Android service, just an instance that's accessible to everyone. Is that frowned upon in Android? Is there a better design that fits this problem?
Editted: Even if I call startService and then bind to it, nothing guarantees that the service instance will exist as long as the application is running. Android can kill sticky services if resources are low. Killing the service will cause the application to malfunction, and I can't have that.
Even if I call startService and then bind to it, nothing guarantees that the service instance will exist as long as the application is running.
Correct.
Android can kill sticky services if resources are low.
Also correct. All "sticky" means is that Android might restart the service.
Killing the service will cause the application to malfunction, and I can't have that.
It is impossible to create a service that is guaranteed to run forever. For starters, users can get rid of your service whenever they want, because users detest developers who have pointless services that run forever. Writing everlasting services is necessary only in very few cases; otherwise, it's just sloppy programming.
The only solution I can see is using a singleton for the service. And then it doesn't really have to be an Android service, just an instance that's accessible to everyone. Is that frowned upon in Android?
Singletons (a.k.a., static data members) will go away when the process is terminated. The process will be terminated eventually, particularly if there are no active services and none of your activities is in the foreground..
Call startService and in onStartCommand return START_STICKY. It should keep the service going.
You may also want to look into foreground services:
http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)
Yo have to create persistent service. Refer to this manual.
In a few words - don't call bindService, call startService.