Android: keep Service running when app is killed Android: keep Service running when app is killed android android

Android: keep Service running when app is killed


All the answers seem correct so I'll go ahead and give a complete answer here.

Firstly, the easiest way to do what you are trying to do is launch a Broadcast in Android when the app is killed manually, and define a custom BroadcastReceiver to trigger a service restart following that.

Now lets jump into code.


Create your Service in YourService.java

Note the onCreate() method, where we are starting a foreground service differently for Build versions greater than Android Oreo. This because of the strict notification policies introduced recently where we have to define our own notification channel to display them correctly.

The this.sendBroadcast(broadcastIntent); in the onDestroy() method is the statement which asynchronously sends a broadcast with the action name "restartservice". We'll be using this later as a trigger to restart our service.

Here we have defined a simple Timer task, which prints a counter value every 1 second in the Log while incrementing itself every time it prints.

public class YourService extends Service {public int counter=0;    @Override    public void onCreate() {        super.onCreate();        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)            startMyOwnForeground();        else            startForeground(1, new Notification());    }    @RequiresApi(Build.VERSION_CODES.O)    private void startMyOwnForeground()    {        String NOTIFICATION_CHANNEL_ID = "example.permanence";        String channelName = "Background Service";        NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);        chan.setLightColor(Color.BLUE);        chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);                NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        assert manager != null;        manager.createNotificationChannel(chan);        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);        Notification notification = notificationBuilder.setOngoing(true)                .setContentTitle("App is running in background")                .setPriority(NotificationManager.IMPORTANCE_MIN)                .setCategory(Notification.CATEGORY_SERVICE)                .build();        startForeground(2, notification);    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        super.onStartCommand(intent, flags, startId);        startTimer();        return START_STICKY;    }    @Override    public void onDestroy() {        super.onDestroy();        stoptimertask();        Intent broadcastIntent = new Intent();        broadcastIntent.setAction("restartservice");        broadcastIntent.setClass(this, Restarter.class);        this.sendBroadcast(broadcastIntent);    }    private Timer timer;    private TimerTask timerTask;    public void startTimer() {        timer = new Timer();        timerTask = new TimerTask() {            public void run() {                Log.i("Count", "=========  "+ (counter++));            }        };        timer.schedule(timerTask, 1000, 1000); //    }    public void stoptimertask() {        if (timer != null) {            timer.cancel();            timer = null;        }    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }}

Create a Broadcast Receiver to respond to your custom defined broadcasts in Restarter.java

The broadcast with the action name "restartservice" which you just defined in YourService.java is now supposed to trigger a method which will restart your service. This is done using BroadcastReceiver in Android.

We override the built-in onRecieve() method in BroadcastReceiver to add the statement which will restart the service. The startService() will not work as intended in and above Android Oreo 8.1, as strict background policies will soon terminate the service after restart once the app is killed. Therefore we use the startForegroundService() for higher versions and show a continuous notification to keep the service running.

public class Restarter extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        Log.i("Broadcast Listened", "Service tried to stop");        Toast.makeText(context, "Service restarted", Toast.LENGTH_SHORT).show();        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            context.startForegroundService(new Intent(context, YourService.class));        } else {            context.startService(new Intent(context, YourService.class));        }    }}

Define your MainActivity.java to call the service on app start.

Here we define a separate isMyServiceRunning() method to check the current status of the background service. If the service is not running, we start it by using startService().

Since the app is already running in foreground, we need not launch the service as a foreground service to prevent itself from being terminated.

Note that in onDestroy() we are dedicatedly calling stopService(), so that our overridden method gets invoked. If this was not done, then the service would have ended automatically after app is killed without invoking our modified onDestroy() method in YourService.java

public class MainActivity extends AppCompatActivity {    Intent mServiceIntent;    private YourService mYourService;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mYourService = new YourService();        mServiceIntent = new Intent(this, mYourService.getClass());        if (!isMyServiceRunning(mYourService.getClass())) {            startService(mServiceIntent);        }    }    private boolean isMyServiceRunning(Class<?> serviceClass) {        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {            if (serviceClass.getName().equals(service.service.getClassName())) {                Log.i ("Service status", "Running");                return true;            }        }        Log.i ("Service status", "Not running");        return false;    }    @Override    protected void onDestroy() {        //stopService(mServiceIntent);        Intent broadcastIntent = new Intent();        broadcastIntent.setAction("restartservice");        broadcastIntent.setClass(this, Restarter.class);        this.sendBroadcast(broadcastIntent);        super.onDestroy();    }}

Finally register them in your AndroidManifest.xml

All of the above three classes need to be separately registered in AndroidManifest.xml.

Note that we define an intent-filter with the action name as "restartservice" where the Restarter.java is registered as a receiver.This ensures that our custom BroadcastReciever is called whenever the system encounters a broadcast with the given action name.

<application    android:allowBackup="true"    android:icon="@mipmap/ic_launcher"    android:label="@string/app_name"    android:supportsRtl="true"    android:theme="@style/AppTheme">    <receiver        android:name="Restarter"        android:enabled="true"        android:exported="true">        <intent-filter>            <action android:name="restartservice" />        </intent-filter>    </receiver>    <activity android:name="MainActivity">        <intent-filter>            <action android:name="android.intent.action.MAIN" />            <category android:name="android.intent.category.LAUNCHER" />        </intent-filter>    </activity>    <service        android:name="YourService"        android:enabled="true" >    </service></application>

This should now restart your service again if the app was killed from the task-manager. This service will keep on running in background as long as the user doesn't Force Stop the app from Application Settings.

UPDATE: Kudos to Dr.jacky for pointing it out. The above mentioned way will only work if the onDestroy() of the service is called, which might not be the case certain times, which I was unaware of. Thanks.


If your Service is started by your app then actually your service is running on main process. so when app is killed service will also be stopped. So what you can do is, send broadcast from onTaskRemoved method of your service as follows:

 Intent intent = new Intent("com.android.ServiceStopped"); sendBroadcast(intent);

and have an broadcast receiver which will again start a service. I have tried it. service restarts from all type of kills.


In your service, add the following code.

@Overridepublic void onTaskRemoved(Intent rootIntent){    Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());    restartServiceIntent.setPackage(getPackageName());    PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);    AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);    alarmService.set(    AlarmManager.ELAPSED_REALTIME,    SystemClock.elapsedRealtime() + 1000,    restartServicePendingIntent);    super.onTaskRemoved(rootIntent); }