Android Background Service is restarting when application is killed

41,327

Solution 1

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).

Solution 2

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.

Solution 3

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.

Share:
41,327
duncanportelli
Author by

duncanportelli

Updated on August 15, 2020

Comments

  • duncanportelli
    duncanportelli almost 4 years

    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;
    }
    
  • fedepaol
    fedepaol about 11 years
    I think his not referring to an IntentService (which has the onHandleINtent method) but to a plain one (Service).
  • fedepaol
    fedepaol about 11 years
    How do you "kill" the application? And how do you know that onCreate() and onStart() are called over and over?
  • duncanportelli
    duncanportelli about 11 years
    I kill the application by swiping away the app in the Recent Apps tray (I have a Galaxy Nexus running on Android 4.1.1). I know the onCreate() and onStart() are called over again because I display a toast notification at the beggining of the 2 methods
  • duncanportelli
    duncanportelli about 11 years
    Sorry, I am a newbie. Yes I am referring to a 'plain service'
  • fedepaol
    fedepaol about 11 years
    Do you bind the activity to the service?
  • duncanportelli
    duncanportelli about 11 years
    I stop the service when the user presses a button from the activity. My question is: how can I keep the service running smoothly, without restarting, even if the application is killed?
  • fedepaol
    fedepaol about 11 years
    Need to go out now. I'll dig into it when I get back.
  • duncanportelli
    duncanportelli about 11 years
    Ok. Thanks mate. Have fun :)
  • duncanportelli
    duncanportelli about 11 years
    Thanks for your application. When I kill the application that you sent me, although the onDestroy() isn't called, the service doesn't keep running and it ends. I can check this from my task manager. When I changed the service to START_STICKY, and killed the application, the service is restarted. I think I have to live with it.
  • sam
    sam about 9 years
    START_NOT_STICKY is for short-lived services (where you don't mind if it gets closed immediately), as described by the quoted documentation above. Even if it avoids this problem somehow, it doesn't seem a sensible solution for a long-lived background service. (I would have thought it might stop Android restarting the service, but not stop it killing it in the first place.)
  • Nicu Surdu
    Nicu Surdu almost 9 years
    This doesn't seem to work for me, at least not in Android 5.1.1