Start_Sticky Does Not Work on Android Kitkat

START_STICKY does not work on Android KitKat

This is not a 100% working solution but it's the best so far as it almost completely eliminates the problem. So far I integrated this solution along with overriding onTaskRemoved (See this answer) and a keep-alive notification (See this answer).
Additional answers are very appreciated !

After further investigation, it seems that the bug already exists in Jelly Bean and looks like there is a solution for that (At least in my case that seems to work. will keep on testing and update the answer if required).

From what I observed this only happens with services that receive broadcasts set by AlarmManager.

To reproduce the bug follow these steps:

  1. Start the app
  2. start the service as a foreground service (use startForeground for that) from within the app
  3. Swipe the app from "Recent Apps" list
  4. Send a broadcast that is handled by the service
  5. The service is killed !

Using adb shell dumpsys >C:\dumpsys.txt you can monitor the state of the service between the different steps. (look for Process LRU list in the dumpsys output)
on steps 2 and 3 you will see something like this:

Proc # 2: prcp  F/S/IF trm: 0 11073:<your process name>/u0a102 (fg-service)

Specifically, notice the F/S/IF and the (fg-service) that indicate the service is running as a foreground service (more details on how to analyze the dumpsys at this link: https://stackoverflow.com/a/14293528/624109).

After step 4 you will not see your service in the Process LRU list.
Instead, you can look at the device logcat and you will see the following:

I/ActivityManager(449): Killing 11073:<your process name>/u0a102 (adj 0): remove task

What seems to be causing that behavior is the fact that the received broadcast takes the service out of its foreground state and then killed.

To avoid that, you can use this simple solution when creating your PendingIntent for the AlarmManager (Source: https://code.google.com/p/android/issues/detail?id=53313#c7)

AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent("YOUR_ACTION_NAME");
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, intent, 0);

Pay attention to the following steps:

  1. Call addFlags on the intent and use FLAG_RECEIVER_FOREGROUND
  2. Use a non-zero request code in PendingIntent.getBroadcast

If you leave any of those steps out it will not work.

Note that the FLAG_RECEIVER_FOREGROUND was added on API 16 (Jelly Bean) so it makes sense that this is when the bug first appeared...

Most likely that KitKat is just more aggressive when it comes to killing processes and this is why it was emphasized with KitKat, but looks like this was already relevant on Jelly Bean.

Note 2: Notice the details in the question about the service configuration - running in a separate process, as a foreground service, with endWithTask set to false in the manifest.

Note 3: The same thing happens when the app receives the android.appwidget.action.APPWIDGET_CONFIGURE message and shows a configuration activity for a new widget (Replace step 4 above with creating a new widget). I found that only happens when the widget provider (the receiver that handles android.appwidget.action.APPWIDGET_UPDATE) is set to run on a different process than the activity process. After changing that so both the configuration activity and the widget provider are on the same process, this no longer happens.

START_STICKY not working

May be useful for someone--

This problem has nothing to do with devices with AOSP based ROMs.So android 4.4.2 version is not an issue.

So there are some devices (HUAWEI,LAVA,XIAOMI) are shipped with pre-installed start managers or energy savers, and they run on customized android ROMs. so these devices generally dont entertain a sticky service.

So possible option is to implement something like watchdog timer and check the service in between, if not started, the service can be run again. Possible implications may be on battery consumption though.

Android service not restarting in lollipop

Finally I achieved with help of Evernote JobService

Github link - https://github.com/evernote/android-job

Step 1: Add evernote jobservice dependency

implementation 'com.evernote:android-job:1.3.0-alpha03'

Step 2: Create DemoJobCreator.java class

public class DemoJobCreator implements JobCreator {

@Override
@Nullable
public Job create(@NonNull String tag) {
switch (tag) {
case DemoSyncJob.TAG:
return new DemoSyncJob();
default:
return null;
}
}
}

Step 3: Create DemoSyncJob.java class

public class DemoSyncJob extends Job {

public static final String TAG = ">>>> job_demo_tag";

@Override
@NonNull
protected Result onRunJob(Params params) {
// run your job here
Log.d(TAG, "onRunJob: ");
if(!isMyServiceRunning(this.getContext(), TestService.class)){
Intent intent=new Intent(context,TestService.class);
context.startService(intent);
}
scheduleJob();
return Job.Result.SUCCESS;
}

public static void scheduleJob() {
new JobRequest.Builder(DemoSyncJob.TAG)
.setExecutionWindow(2_000L, 2_000L)
//.setPeriodic(900000) -> recommended. but it will work after 15 min (if you used this no need scheduleJob(); inside onRunJob();)
.build()
.schedule();
}

public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
try {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
}catch (Exception e){
Log.e(TAG, "isMyServiceRunning: ",e );
}
return false;
}
}

Step 4: In your Application file (If not available create it) add following line in onCreate()

 JobManager.create(this).addJobCreator(new DemoJobCreator());

Step 5: Finally start JobService in your Activity

DemoSyncJob.scheduleJob();

This JobService will check service running or not (every 2 second) If service not running it will restart the service.

Disclaimer : This may be not right solution. But it will 100% working.

I hope it helps atleast anyone in future.

Android system killed my service when I clear all recent app

A long running service needs the following to make it less likely to be terminated:

  1. Return START_STICKY from onStartCommand(). With this, system will re-start the service even if it has to be stopped for resources limitations.

  2. When the service is not bound to any UI component (e.g an Activity), The service must go in foreground mode by showing a foreground notification. Foreground services are less likely to be terminated by system.

  3. Set the attribute "stopWithTask"=false in corresponding <service> tag of manifest file.

Also, note that devices from some manufacturers will terminate services even with above properties due to customization:

  1. Custom task managers.
  2. Battery saving features that can prohibit non-system services.

Some application services do need to stay in background and have to be aggressively kept alive. Though this method is not recommended, but following steps can be done:

  1. Add triggers for service start : Such as Boot Complete, and Network Connected broadcasts.

  2. If service receives intents/broadcasts FLAG_RECEIVER_FOREGROUND in the intent.

  3. An extreme resort is to manually schedule a pending intent for service restart, with AlarmManager, when onTaskRemoved() is called.

Also, see:

  1. START_STICKY does not work on Android KitKat

Service in my application isnt being recreated

I belive you have encountered problem that is issued as a bug here:

https://code.google.com/p/android/issues/detail?id=63793

but probably google finds it more like a feature.

If your service is supposed to run all the time then think about making it foreground service.



Related Topics



Leave a reply



Submit