6

I am running a service in the foreground. Sometimes it is terminated, presumably for memory reasons (although I'm not 100% sure of that from the LogCat log). Other services that are terminated are scheduled for a restart in 5000ms, but looking at the log, the restarts of my service are very long, for example:

11-15 15:39:48.756: W/ActivityManager(375): Scheduling restart of crashed service com.example.app/com.example.SensorService in 1019562ms

What could account for this? How is the restart interval set? I have seen some suggestions that services with notifications are restarted with a shorter delay, but my service does have a notification.

2
  • Have you tried using startForeground and see if it helps?
    – Kai
    Commented Nov 16, 2013 at 4:19
  • It is running with startForeground.
    – Catherine
    Commented Nov 16, 2013 at 4:30

3 Answers 3

14
+50

From com/android/server/am/ActiveServices.java (not exposed)

// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;

// How long a service needs to be running until restarting its process
// is no longer considered to be a relaunch of the service.
static final int SERVICE_RESTART_DURATION = 5*1000;

// How long a service needs to be running until it will start back at
// SERVICE_RESTART_DURATION after being killed.
static final int SERVICE_RESET_RUN_DURATION = 60*1000;

// Multiplying factor to increase restart duration time by, for each time
// a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
static final int SERVICE_RESTART_DURATION_FACTOR = 4;

// The minimum amount of time between restarting services that we allow.
// That is, when multiple services are restarting, we won't allow each
// to restart less than this amount of time from the last one.
static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;

// Maximum amount of time for there to be no activity on a service before
// we consider it non-essential and allow its process to go on the
// LRU background list.
static final int MAX_SERVICE_INACTIVITY = 30*60*1000;

What's happening for you probably is your service is dying quicker then SERVICE_RESET_RUN_DURATION and then restart time is multiplied by SERVICE_RESTART_DURATION_FACTOR.

Starting from line #881:

            // If it has been a "reasonably long time" since the service
            // was started, then reset our restart duration back to
            // the beginning, so we don't infinitely increase the duration
            // on a service that just occasionally gets killed (which is
            // a normal case, due to process being killed to reclaim memory).
            if (now > (r.restartTime+resetTime)) {
                r.restartCount = 1;
                r.restartDelay = minDuration;
            } else {
                if ((r.serviceInfo.applicationInfo.flags
                        &ApplicationInfo.FLAG_PERSISTENT) != 0) {
                    // Services in peristent processes will restart much more
                    // quickly, since they are pretty important.  (Think SystemUI).
                    r.restartDelay += minDuration/2;
                } else {
                    r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
                    if (r.restartDelay < minDuration) {
                        r.restartDelay = minDuration;
                    }
                }
            }

Line below does the backing off your service.

r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;

So you should fix the case if your service is dying before running for SERVICE_RESET_RUN_DURATION.

7
  • This isn't quite the case for me. Nevertheless, this is the most helpful answer as it points me in the right direction and shows me where the restart duration is being determined.
    – Catherine
    Commented Nov 27, 2013 at 23:07
  • What do you mean by dying. I am never killing my service since I am running a messaging app. Does that mean crash? Commented Oct 26, 2015 at 15:24
  • @user2223032 yes that might be very well be the case.
    – auselen
    Commented Oct 26, 2015 at 20:31
  • Thanks. My application is not crashing so don't know if there can be service crash. However since I am developing it's frequent install and uninstall. Also I put my service as start_redelivered_intent and now changed it to start_sticky Commented Oct 27, 2015 at 5:48
  • @user2223032 I think this answer was also about if you start/stop service too quickly you may get this penalty.
    – auselen
    Commented Oct 27, 2015 at 7:33
2

First of all I think you will call the Service class from an Activity class or from any BroadCastReceiver class.

You would like to start the service after some specific or may be after 5000ms . Though your question is not clear for me. Still as per my knowledge you have to call the service from your service class. For example:

    public class UpdateWidgetServiceDemo extends Service {

      public static int numberOfItems=0;
      String resultURL="";

        //numberOfItems=0;
        private static  String LOG = "testwidgets";

        ArrayList<String> feedsPubDate;

          @TargetApi(Build.VERSION_CODES.GINGERBREAD)
        @SuppressWarnings("deprecation")
        @Override
          public void onStart(Intent intent, int startId) {

              StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
              StrictMode.setThreadPolicy(policy);
              Log.i(LOG, "Called");
            // Create some random data

            feedsPubDate=new ArrayList<String>(); 

            /////////////////////////////////////////////////////////////////////

    //        SharedPreferences sp = getSharedPreferences("updateOptions", 0);
    //        int updatePeriod=sp.getInt("UpdatePeriod", -1);

            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, 10);

            Intent intent1 = new Intent(this, UpdateWidgetServiceDemo.class);

            PendingIntent pintent = PendingIntent.getService(this, 0, intent1, 0);

            AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            int i;
            i=15;
            alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),  i* 1000, pintent);
}
.
.
.

Here the main important part is :

Calendar cal = Calendar.getInstance();
                cal.add(Calendar.SECOND, 10);

                Intent intent1 = new Intent(this, UpdateWidgetServiceDemo.class);

                PendingIntent pintent = PendingIntent.getService(this, 0, intent1, 0);

                AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                int i;
                i=15;
                alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),  i* 1000, pintent);

I think your problem will be solved.

Enjoy!!!

1

You can set the update interval using method below, Service will be restarted every 1 minute.:

void setServiceIntervalAlarm()
{
    // set alarm for next 60 seconds
    Intent updateIntent = new Intent();
    updateIntent.setClass(this, CheckOutRequestsService.class);

    PendingIntent pendingIntent = PendingIntent.getService(this, 23, updateIntent, 0);
    // Schedule alarm, and force the device awake for this update
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    long nextUpdate = 60000;
    alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), nextUpdate, pendingIntent);
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.