Prevent Android Service From Being Killed By OS - java

I have created a service that is returning START_STICKY at the onStartCommand. However, after sometime, I notice that my app has been killed by the OS.
Is there any method/piece of code that I can use to prevent the app from being killed by the OS? I know this may not fall under the best practices.
Or is there some other method that we can use like repeatedly check if the app is running, and to start the app if it is not?
Your insight on this is very much appreciated.
Cheers

The best way to stop a service being killed by android is to create a persistant notification. This will make android keep the service alive at all costs because it displays something visible.

You cannot prevent your process from being killed. If OS decide to kill your processes you will be killed. Period.
The START_STICKY will not do any magic os other answer incorrectly tells - docs about that value say:
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.

Related

Is a START_STICKY service restarted after application killed itself

So if I understand right, the difference between START_STICKY and START_NOT_STICKY is that the first will be restarted by the system, in case it kills it.
Does anyone know whether this also happens when I kill my application using Process.killProcess(Process.myPid())? Or does the system only restart the service if the service was actually being killed externally, not from within the application process?
Not always, you can't depend on START_STICKY for continuing running the service. Better way is to use startForeground for continuing running or if you want to repeat specific task then schedule your service on specific time. Also, manage it when the phone is Restarted as well.
Notification.Builder builder = new Notification.Builder(getBaseContext())
.setContentTitle("");
.setContentText("Your content text");
startForeground(1, builder.build());
Yes, the START_STICKY service is restarted after the application is killed by the Android System.
Until and unless you call stopService() method from an app component or stopSelf() from within the service, the service will be restarted if the app is killed.
But you can always make the service run using startForeground() method, in which you will have to show a notification in the status bar for your service. If you create a service using this method, your service will run at the same priority as an active activity. This means that it is highly unlikely that your service will be stopped, and no restart would be required.

How to kill a Service [duplicate]

I am developing an application in which a background service is created to collect sensor data. I am starting the service from my activity:
startService(new Intent(this, MyService.class));
I created the service so if the application is destroyed, the background service still continues to collect data. I tried this, and it worked to a certain extent. My problem is that when I kill the application, the service seems to restart because the onCreate() service and the onStart() methods are invoked. Is there any way with which the service isn't restarted please?
UPDATE:
As suggested in an answer below, I added the following method in the service but no luck.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
It depends on the value returned in onStartCommand.
You must return START_NOT_STICKY
According to the documentation:
For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand(): START_STICKY is used for services that are explicitly started and stopped as needed, while START_NOT_STICKY or START_REDELIVER_INTENT are used for services that should only remain running while processing any commands sent to them
In short:
If you return START_STICKY the service gets recreated whenever the resources are available. If you return START_NOT_STICKY you have to re-activate the service sending a new intent.
Since all of this triggered my curiosity, I made a sample app to test this. You can find the zip with all the sources here
There are a startService button and a stopService button that do what you would expect from them.
The service returns START_NOT_STICKY in onStartCommand.
I placed toasts in onCreate, onStartCommand and onDestroy.
Here what happens:
If I press start, onCreate and onStart are called
If I press stop, onDestroy is triggered
If I press start twice, onCreate is called once and onStartCommand twice
So it behaves as one would expect.
If I start the service and kill the app as you described, onDestroy does not get called but neither onCreate or onStart.
If I get back to the app and I press start again, onCreate gets called which means that, as I wrote before, START_NOT_STICKY prevents the service to getting restarted automatically.
I guess you have something else in your app that starts the service again (maybe a pending intent).
The app and the service live on the same process, which means when the app is killed so is your service. Changing the return value of onStartCommand doesn't affect this process. It simply tells the Service to either start/stop when you tell it or when it's finished doing what it needs to. As mentioned in your comment to your original post, setting it as a foreground process worked, but that's really just forcing the service to have a high priority, not solving the problem.
To change the Service so that it's killed separately and assuming it's a started service rather than a bound service due to the use of onStartCommand, specify a process name in the manifest for that Service.
From the Process and Threads Developer Guide:
The manifest entry for each type of component element— <activity>, <service>, <receiver>, and <provider>—
supports an android:process attribute that can specify a
process in which that component should run. You can set
this
attribute so that each component runs in its own process or so
that some components share a process while
others do not. You can also set android:process so that
components of different applications run in the same
process—provided that the applications share the same
Linux user ID and are signed with the same certificates.
Android might decide to shut down a process at some
point, when memory is low and required by other
processes that are more immediately serving the user.
Application components running in the process that's
killed are consequently destroyed. A process is started
again for those components when there's again work for them to do.
From <service> in Manifest File:
android:process
The name of the process where the service is to run.
Normally, all components of an application run in the default process
created for the application. It has the same name as the application
package. The element's process attribute can set a
different default for all components. But component can override the
default with its own process attribute, allowing you to spread your
application across multiple processes.
If the name assigned to this
attribute begins with a colon (':'), a new process, private to the
application, is created when it's needed and the service runs in that
process. If the process name begins with a lowercase character, the
service will run in a global process of that name, provided that it
has permission to do so. This allows components in different
applications to share a process, reducing resource usage.
Not sure why the other answer that mentioned this was down voted. I've used this method in the past and, today, created a simple one Activity app with a Service on a different process just to make sure I wasn't crazy. I used Android Device Monitor to kill the app's process. You can see both, separate processes in ADM and can see that when the app's process is killed, the Service's is not.
Start not sticky doesn't work above kitkat, and the other onTaskRemoved not working above Marshmellow.
onTaskRemoved could be used by handled some exceptions. Did not worked on that. But try that one.
If you are using an IntentService, it has an
onHandleIntent()
method where you should place the code that needs to be executed. It is executed in a separate thread (not a UI thread where your application runs) therefore your app shouldn't affect it. When the code has finished executing, the thread is terminated and the service is stopped automatically.
I ran into the same problem and was able to resolve it by making the service run in a global process. You do this by adding the following to the manifest tag:
process="com.myapp.ProcessName"
(Make up whatever name.)
When I did this I found that my service wasn't killed (and restarted) when the app is swiped off the list. Presumably this is because the app process is killed when you swipe it off, but global service processes are not.
The disadvantage of this is that communication between your app and service now has to be via the IBinder interface; you can't directly call functions in the application or service from the other one, because they're running in different processes.
I know its much late to answer this question, but may be it can be helpful to others. This really helped me for my Music Player App.
If there are services which can be disruptive or can affect the user experience like music etc , then in that case you have to use Notification and when service is started successfully, then create the Notification and use the function
startForeground(int Notification_id,Notification);
This will run your service in background without restarting and reinvoking its methods
https://developer.android.com/reference/android/app/Service.html

My app's Service keeps being killed

I have a pool of AsyncTasks which pass state data back to the service that executed them, but they keep being killed by Android.
I can't use an IntentService because the Service is keeping track of State used by UI and AsyncTasks.
How do I:
1) keep the service from being killed
2) Replace either service or AsyncTask with something better for this use case?
You should use foreground service. Android OS can kill service if it is running short on resources, but it will always spare foreground service.
The Android system will force-stop a service only when memory is low
and it must recover system resources for the activity that has user
focus. If the service is bound to an activity that has user focus,
then it's less likely to be killed, and if the service is declared to
run in the foreground (discussed later), then it will almost never be
killed.
Note: Another thing you should also consider
Caution: A service runs in the main thread of its hosting process—the
service does not create its own thread and does not run in a separate
process (unless you specify otherwise). This means that, if your
service is going to do any CPU intensive work or blocking operations
(such as MP3 playback or networking), you should create a new thread
within the service to do that work. By using a separate thread, you
will reduce the risk of Application Not Responding (ANR) errors and
the application's main thread can remain dedicated to user interaction
with your activities.

Is it possible that the service still runs after the app got killed with task manager?

Hello im triying to run a service in background that it doesn't stop when app is destroyed by task manager. The idea of the service is verify every "x" min if there a new insert in a database that i got in a server.
The service is running great even if i close the app but when i use the task manager to destroy my app all the threads are closed too.
So i want to know if its possible to run a thread that ask in background forever unless user cancel it in the app itself, that ignore the destroy caused by task manager so in the future i can use notification bar to tell the user that a new insert happened in the database.
Tryed:
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
askServer(); // i made a timertask that ask every "x" minute
return START_STICKY;
}
As i read START_STICKY should run again the service if it get killed for some reason and i know that this can be done since some app get closed by taskmanager and still get notifications from it as whatsapp,bbms and others. Please tell me if im wrong in anything and thank you for reading!.
UPDATE: Im not trying to break any law or security rule from Android and im not trying to ignore the stoping services option from an app in settings. I want that the service that listen for new incoming "events " inserts in my case keep running after user used the interface that appear when you press home for a while :
UPDATE : sorry for talking to much about this app but is the one that i can use as an example. In whatsapp when i close the app by the interface that i showed above the process and services are killed but after a couple of second they relaunch, this is exactly what i want to do to keep user informed about database events. From setting you still can stop the service without problem or even i can put the option in the app itself to stop notifiying.
Is a bad implementation call in OnDestroy() method an instance of the service so it relaunch after destroy?
UPDATE : welp looks like my service is still running on background after i close the app. I will just have to work on my service design to not waste battery life and resources. Also i was using the log.i() to check if service was running, looks like when main process closes i can't use log or toast just notifications ( still not implemented) because the service is there running just won't show in log .
UPDATE : now is working using using startForeground(0, null). In future i will send a notification to show when a event on database happen building it and calling startForeground(1, notification).
For services, look at Settings -> Applications -> Services. and see if it is running.
However, poorly designed services may run more often or perform syncing operations. So yes it is possible.
I had a problem similar to this when developing my first android game; force-stop was the only way to kill it.
START_NOT_STICKY will kill the background service when you swipe the app away from the task manager. START_STICKY is, as the name implies, "sticky", Meaning it sticks to the android system even when the app is gone.
That's from my experience, anyway.

How to force an application to stay open?

I have seen apps like Lookout, JuiceDefender, and MagicJack run in the background indefinitely, unless force closed by a user directly through the task manager. (And even then, in Gingerbread, it wouldn't close unless you browsed to the application that was running under "Downloaded Apps" in the settings and force closed it once you were at the menu where you have options to manage the app like "Clear Memory" and "Force Close".
I am wondering how this is accomplished? I need to do something similar for an app of mine but I don't know how to avoid the Android OS's automatic task killing.. And don't say it's not possible because if that were true, JuiceDefender, MagicJack, and Lookout would not work.
What you can have is a service that stays alive indefinitely. You achieve that returning Service.START_STICKY on your Service's onStartCommand method.
Whenever the os needs resources and chooses to kill your app, your service will be respawned as soon as the resources are available again.
Bear in mind that having an application that is continuously alive will result in consuming the phone's battery. You should (at least) notify the user with a notification that your app is still alive in the background.
On top of that, you can register a broadcast receiver for the BOOT_COMPLETED event in order to restart your service while the device gets restarted. Yet, bear in mind that this could result in eating the phone's battery and so be careful on what you are doing in the service.
I believe these apps are launching a Service when their Activity get started (i.e when onCreate() is called).
A Service keeps running when the application get paused. When the Service is launched, you may return START_STICKY in your onStartCommand.
Also, to prevent a Service from being killed by Android's memory killer, you can specify that your Service is important to the user by calling startForeground(). Android Developers website states that :
A foreground service is a service that's considered to be something
the user is actively aware of and thus not a candidate for the system
to kill when low on memory.
I am creating an app and I have to use one or more of the following super functions inside OnCreate():
onDestroy()
onPause()
onResume()
onSaveInstanceState()
to close an app completely from the memory. And also do not use Activity.finish() method. Usually Android does a pretty good job in closing the app when memory is needed, called pop out of stack and not recommended to forcefully stay in memory, unless there is a very very good reason to. Hope it helps.
You can also check the Android DOC website for more information and examples to your request.
You need to start a service. Services runs in background and is useful to push alerts.
This some links about it:
http://developer.android.com/guide/components/services.html
http://www.vogella.com/articles/AndroidServices/article.html
In the service onStartCommand method return "START_STICKY".
http://developer.android.com/guide/components/services.html
/Thomas

Categories