I'm just reading up on the use of services to keep an app alive in the background.
A few things are not quite clear to me.
1: Once a service has started, does it stay alive when the main app gets destroyed by Android? (I know it does with OnPause() and OnStop() )
2: If anything is declared in memory for the service, is there a way to access this as well from my app?? (EG service just records the GPS to see if you're moving or standing still. from the main app I want to see how much of each is recorded while the main app was inactive)
I know these are fairly general questions, I'm just reading up on this part of Android programming, and would like to modify a program in the near future. So I have no code to go with the question yet
Thanks,
BBBwex
Once a service has started, does it stay alive when the main app gets destroyed by Android?
An app does not get destroyed. Activities get destroyed. Apps have their process terminated.
A service will run in the process until:
there are no more bound connections (i.e., via bindService()) and
if the service was started with startService(), it was stopped with stopService() or stopSelf()
Of course, once the process is terminated, the service (and everything else) is gone.
If anything is declared in memory for the service, is there a way to access this as well from my app?
Your service is part of your app. I am going to assume here that by "app" you mean "activity".
Your service has any number of ways of publishing information in ways that an activity can monitor and use, including:
Service writes the data to a ContentProvider, which updates the activity via a Loader or ContentObserver
Service sends messages to the activity, via LocalBroadcastManager, a third-party message bus like Otto, a Messenger tied to a Handler, etc.
Service stores a cache of data in a static data member, which the activity reads (or perhaps polls)
The activity simply reads the data out of whatever persistent data store the service uses (e.g., SharedPreferences) as needed
Etc.
Related
I have an Android Library with a service, which I implemented using AIDL. I want a single instance, cross application to be used with other apps. So I have a base app with the service and I managed to make the library for other apps to use the same instance.
My problem comes when I close all apps using the service, because for every app, the on destroy unbinds from the service, but the service is still running.
Also, I'm only using the service by binding, not by startService().
I checked through android studio that the service is running after closing the apps, and the counter I have on the service for each bind/unbind call is 0!. I increment the counter when there is a call to bind, and decrease for calls to unbind. My only way to make the service stop is by opening the base app, which has the service defined and closing it.
Edit: Also noticed that onBind is being called only once, even for other apps that are binding, but the reference for all those apps is still the same service, they share the same information and only one Service is shown in the android studio.
Edit: I've also observed that if one of the apps using the service is the base app, if I close it, the service dies and another one is started, the other apps don't notice the change, they keep using the service as if nothing happened, which is understandable because it's a remote service.
What is happening and what can I do about it?
For the two points being questioned:
I was able to verify what CommonsWare said that the process in which the service is run is still up, but the service itself is not. At first I had a thread running in the service after every app unbound, but after making sure it wasn't up in the end made the service be destroyed.
The second issue, regarding the service being destroyed while still bound with other activities was solved by seeing this link which describes a bug in android that kills services when it shouldn't. My case was simply solved by making my service run in the foreground, which I didn't know was possible.
After some tests I verified the service is still intact as long as any app is bound with it, and that the service indeed is destroyed correctly after no more app is bound.
With respect to Process lifecycle, Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes. To determine which processes to keep and which to kill, the system places each process into an "importance hierarchy" based on the components running in the process and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest importance, and so on, as necessary to recover system resources.
One of the classification is :
Foreground Process : A process that is required for what the user is currently doing. A process is considered to be in the foreground if any of the following conditions are true:
1. It hosts an Activity that the user is interacting with.(the Activity's onResume() method has been called).
2. It hosts a Service that's bound to the activity that the user is interacting with.
3. It hosts a Service that's running "in the foreground" —the service has called startForeground().
4. It hosts a Service that's executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).
5. It hosts a BroadcastReceiver that's executing its onReceive() method.
What can be real life examples of scenarios given above I am asking this because it will help me and others as well in differentiating between this situations.
1)THe app that is currently on top of the stack (the one the user is using)
2)An app with an Activity that has called bindService on any service. The idea is that if it killed that service, it might lose data. An example of this would be a facebook app, which has a background service to fetch data every so often. If the user has it open, it would qualify
3)This is a service that has declared that its feeds data to a UI. An example of this would be a facebook app where the user didn't have an activity with it open
4)This is a service that's just starting or just finishing. This would be pure luck to have happen, but its basically saying it will try to let it start up or finish cleanly before killing it
5)This is any app that's currently responding to an event. An example would be an SMS app that was just notified of an incoming SMS and needs to deal with it. It will be allowed to run until its done, because doing otherwise may lose data.
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.
I have a Networking service that i want to use as a Service. It's a local Service since it's not valid anymore once the application process is dead and no Other applications need to access it.(or should...).
I was pondering if to use the IBinder interface with local reference to the class and decided not to, for the moment.
I have the following issues:
if the service dies, and i know it can during request processing, it's an issue for me, first i've seen it, the process wont die until the net request returns (then the thread dies gracefully), unless kill -9 is used on the process... then i'm not sure what android does with the connections. I'm not sure what's the approach i should take here.(it will be true though even if this was a local thread and not a service...)
if i want the service to listen on a callback and call it once the network processing is done, i'm in a problem, no instances can be passed on using Intents. So i need some other solutions, all the ones i though of sounds bad to me: A. use IBinder to get instance of the network service class then i can call one of it's methods and pass on an instance, this will work since they all run in the same process, BUT requires me to use Async way to get a Network instance which is not so suitable for me. B. Use static member in the Service i can access, then what to i need the service for ? C. use intent to send parameters only to the service, the service will compose a Request out of it and put it in the queue, then once done will send a response using intent which will encapsulate the response (which might be long!) and will also contain the name of the calling class as a string so all the Receivers will know if it's for them or not - BIG overhead of encapsulating data in Intent and search in all the receivers for the right one to get the response.
I don't want to use the service as a local running simple thread since i'm afraid if i'll run it in the root activity i will have to use static container so it will be visible in each activity and if the root will be destroyed for some reason it will take all the service with it, even if i start new task and the process is still alive...
Anyone got some nice ideas on how to approach this thing ?
Eventually i gave up on the service.
The reason to not use the service But to extend Application object and keep the networking class as a member of that Application object, it is started when the application is created, before any activity is created,and it is shut down before the application draws it's last breath. I know application onTerminate might not be called at all times, but if someone will call kill -9 or equivalent on my Application and the process will die killing the application with it, i'm all set as my Service will be destroyed anyway.
The reasons i gave up a service were:
i have a way to keep a worker thread running during the application life cycle.
Since i have and for future planning will have only one application it will still work in the future.
Since It's not connected and started with any specific Activity it wont be affected by their death or by their creations.
it has a context that will last through the lifecycle of the application so i CAN use it to broadcast events using intents.
when the application dies my service dies with it. unless kill -9 and then the system will kill all threads related to the application, mine included, so i'm still good.
Every activity can use getApplication() and cast to my Application object and get the service.
So no need to use binding and complicate my code with it, no need to think of how to start or end the service, if i'd made a service most chances i'll be starting it from the Application anyway (or the root activity), so i think for me and my app this is the best option.