My service is usually started by a BroadcastReceiver for RECEIVE_BOOT_COMPLETED, and is implemented with the START_STICKY flag as follows:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
So In many cases, when the user launches the app, the service would already be running in the background. My activity then binds to it to read information from the service.
However, when the user then destoys the activity (by terminating the app), my service that was already running is now destroyed as well, and it is then restarted via start_sticky. This causes some information that I keep in the service to be lost.
Is there a way to preserve my service instance, and just have my activities come and go, binding to it as needed?
There is no way to make sure a service (or any component of an app) will not be killed. If you have data that needs to be persisted you can use any of these techniques.
http://developer.android.com/guide/topics/data/data-storage.html
SharedPerferences is pretty easy to use.
Here is the section in the developer doc (and the link) that explains how apps are started and stopped by the system.
By default, every app runs in its own Linux process. Android starts
the process when any of the app's components need to be executed, then
shuts down the process when it's no longer needed or when the system
must recover memory for other apps.
http://developer.android.com/guide/components/fundamentals.html
Related
As we all know,Java memory model consists of data (or code), stack and heap segments. I presume that the same is the case with Android. I have a single monolith application (let's consider the code base of this application to be too huge). When I start the application the activities and fragments within the application gets loaded into Dalvik JVM and offloaded. When this is the case, how this works with Service? Let's say I have a STICKY_SERVICE like,
public class CountingNumberService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
for(int i=0; i<100; i++) {
//Do something
}
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
/**
* This has to do with some inter process communication
*/
return null;
}
}
Since the service is STICKY it makes the process behave like a persistent process and it is always running. Now consider I stopped using my application and as a user I believed that application is closed (I'm closing it or clearing it from recents) but since my service is STICKY it would always be running and I assume I would have the following impact,
I would eat user's battery.
Some additional code (other than service) will be running along with the application (?) not sure though. If it's the entire application sitting within data segment then it will not allow other application to run smoothly.
I'm kinda confused on STICKY service on a process (a huge monolith code) and it's impact. Can someone clarify me on this please?
Since the service is STICKY it makes the process behave like a persistent process and it is always running.
No, it does not.
but since my service is STICKY it would always be running
No, it will not.
Quoting the documentation for START_STICKY:
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.
Android is still welcome to terminate your process as it sees fit. All START_STICKY does is encourage Android to restart your service (forking a fresh process along the way) when conditions allow.
I have a function that reads the content of the Android clipboard every two seconds and communicates all changes with a remote server.
This works fine in the app is opened. But I need to be able to continue to log the clipboard changes after the app has been closed.
So I tried an IntentService but it doesn't appreciate long loops.
How can I run my infinite loop in the background?
I have a function that reads the content of the Android clipboard every two seconds and communicates all changes with a remote server.
Polling? You are doing it VERY wrong. You should use OnPrimaryClipChangedListener instead.
EDIT
communicates all changes with a remote server.
I just realised you are basically doing some bad things there and I am bit sceptical believing your users aware you literaly spying on them? Is your app in Google Play if so what's your app package id?
IntentService should be used to process single "request", from another application component, at time.
Use started service which should be more suitable for problem you describe. Started service runs until you manually stops it or until system gets out of resources and kill whole process.
Use START_STICKY as return from onStartCommand() method to automatically start it again when system kills it.
If you also start it in BroadcastReceiver with ACTION_BOOT_COMPLETED action service will be started after device boot.
Implement a Service and make it sticky by returning START_STICKY in onStartCommand (see Documentation):
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
when I open the activity of my project I call the startService(Intent intent) method to start a new Service.
When the activity is destroyed the service shouldn't be killed (because I didn't use the bindService() method), but the fact is that when I close my activity the service is killed and after a second the system creates a new Service (I verified that, the system calls again the onCreate() method of my service). What do I have to do to keep only one service ? Thank you
To have a service running independently of your application's main process and to be sure that Android does not kill it while it's doing something, there are two things you should do/try.
Run your service in a separate process. You can achieve this by adding the following attribute to your service declaration in the manifest:
android:process=":somenamehere"
When your service is running and you do not want it to be killed by the OS, you have to use the startForeground(int id, Notification notification) method. When the service finishes whatever is doing and can be killed by the OS, call stopForeground(boolean removeNotification). "startForeground" requires a notification as argument because every foreground service must display a notification so the user realizes about it
I hope this helps you.
I mean I hold the home button and then kill my activity from the list of app open
That does not "close" an activity. That terminates your process. The user is welcome to terminate your process whenever the user wants, whether via this means or through third-party task manager apps. There is nothing you can do about this -- you cannot stop the user from terminating your process. Since your process will stop for other reasons as well (e.g., sheer old age), you have plenty of reasons to handle this case.
Edit: Please refer to CommonsWare's answer
Old answer: You should override public int onStartCommand(Intent intent, int flags, int startId) method and return START_STICKY value as the mode of your service.
this will keeps your service working when the activity is destroyed or even when you exit your app unless you call stopService(Intent) explicitly
I have an app with one activity and one service. If I kill the activity while the service is running it gets killed too. It is very important for me that the service doesn't get killed. How to make that when the system kills (or I kill it by clearing the "Recent apps" list) the activity the service still remains active until it finishes its job? Thanks in advance!
You can try returning START_STICKY from onStartCommand in your Service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
It is very important for me that the service doesn't get killed
Your processes can be killed at any time, for any reason, based on user activity (recent tasks list, a third-party task manager, "Force Stop" in Settings, etc.) or based on OS needs (system RAM is getting low). You cannot prevent this.
You can take some steps to minimize the odds of the OS deciding on its own to terminate your process, such as using startForeground() on the service, but this does block the user from doing what the user wants with your app's process.
I'm displaying a window from that service so if the service stops then the window disappears.
Presumably, the user wants your window to disappear if the user is explicitly getting rid of your app via the recent tasks list, a task manager, etc. You are certainly welcome to advise users in your documentation of any negative effects that this will have.
You are also welcome to experiment with having that service be in a separate process. My understanding is that this will not help with the recent-tasks list on Android 4.4, though it might on earlier versions of Android. Whether this helps with third-party task managers probably depends on the manager, and this should not help with "Force Stop" from settings. It also means that you will have to deal with IPC, increased system RAM consumption while your main and service processes are both running, etc.
Are you running a bound service? If so, then the system will kill it when the last client activity disconnects (terminates). Here's the blurb from the reference page:
When the last client unbinds from the service, the system destroys the
service (unless the service was also started by startService()).
Can I run a background service Indefinitely ? Will android kill my service if i run it for indefinitely ? How Facebook android application keep running in background for a long time ?? please help me to know about it .
You can use for that these features:
1) Auto-restart service after reboot (Start intent after Reboot)
2) Sticky service mode (http://developer.android.com/reference/android/app/Service.html#START_STICKY)
These features both helps to leave your service started all time as possible.
Android will kill your service if it's running out of memory, but you can do a couple of things to recover from it.
The first thing you can try is to use foreground services, a foreground service is a high priority services that won't be killed unless is completely necessary (note that these services increase battery consumption). You can find an example here using compatibility with older devices, otherwise you only need to call startForeground inside your service.
Another thing you can do is to use some flags in your service to restart it when it gets killed by the OS. You can use 2 different flags (depending on which behaviour you want to reproduce).
START_STICKY will restart your service with an empty intent so everytime you have to recover the data you need to run your service.
START_REDELIVER_INTENT in this case your service will be restarted with the last intent information (it could be that you run your service several times with different information when you want different behaviour).
The flags can be used as follows:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Do your service work
return START_STICKY; //or return START_REDELIVER_INTENT;
}
Depending on what you need use one or another.
Hope it helps :)
There's no way to absolutely protect a Service from being killed.
If you return START_STICKY from onStartCommand(), then even if Service is killed, android will try its best to start it again, when resources are free.