How to prevent our services of Android app from being killed?

Sometimes we need our services to do the work but they often were killed by something like a app management tool, here’s some tricks might help.

Service Flag

Set to START_STICKY, after around 5 sec of service being killed, it will restart, and pass Intent again.

1
2
3
4
5
@Override  
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
}

Use startForeground

Use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.) [From official doc]

Twin Service

Create 2 services to protect each other. they will restart the other service when it was killed.

Evil Trick [Have not tried it yet]

Remain 1px size page in the foreground to stay in a foreground state when application goes to background.

Disguise App as system app [Android 4.0]

Install your apk into /system/app.
Make your app as a system app by changing the proper permissions in a rooted device.

White List

Contact manufacturer.

Listen To The Broadcast

1
2
3
4
5
6
7
8
<receiver android:name="<Name of your package>.<your class>" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
<action android:name="<Name of your package>.<your class>" />
</intent-filter>
</receiver>

BroadcastReceiver,

1
2
3
4
5
6
7
8
9
10
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
//start your sercice
startUploadService(context);
}
if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
//...
}
}

You could use Intent.ACTION_TIME_TICK as better result, this one broadcasts in every minute, however it’s a system broadcast, you can’t config it in manifest.xml, register it in your service or App extends application,

1
2
3
IntentFilter filter = newIntentFilter(Intent.ACTION_TIME_TICK);
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
registerReceiver(receiver, filter);

In your receiver, let’s say it would look like MyBroadcastReceiver extends BroadcastReceiver, override onReceive() method,

1
2
3
4
5
6
7
8
9
10
11
12
13
boolean isServiceRunning = false;
if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
ActivityManager manager = (ActivityManager)ThisApp.getContext().getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service :manager.getRunningServices(Integer.MAX_VALUE)) {
if("so.xxxx.xxxxService".equals(service.service.getClassName())){
isServiceRunning = true;
}
}
if (!isServiceRunning) {
Intent i = new Intent(context, xxxService.class);
context.startService(i);
}
}