很长一段时间后,崩溃的服务重新启动

时间:2013-11-16 00:40:33

标签: android

我正在前台运行服务。有时它会被终止,大概是出于内存的原因(尽管我对LogCat日志并不是100%肯定)。已终止的其他服务计划在5000毫秒内重新启动,但查看日志,我的服务重新启动时间很长,例如:

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

有什么可以解释这个?如何设置重启间隔?我已经看到一些建议,即带有通知的服务会以较短的延迟重新启动,但我的服务确实有通知。

3 个答案:

答案 0 :(得分:14)

来自com/android/server/am/ActiveServices.java(未曝光)

// 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;

您正在发生的事情可能是您的服务比SERVICE_RESET_RUN_DURATION更快死亡,然后重启时间乘以SERVICE_RESTART_DURATION_FACTOR

从第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;
                    }
                }
            }

以下行可以退出您的服务。

r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;

因此,如果您的服务在为SERVICE_RESET_RUN_DURATION运行之前死亡,则应该修复此案例。

答案 1 :(得分:2)

首先,我认为您将从Activity类或任何BroadCastReceiver类调用Service类。

您希望在某些特定时间之后启动该服务,或者可能在5000毫秒之后启动该服务。虽然你的问题对我来说不明确。仍然据我所知,您必须从服务类调用该服务。例如:

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

这里主要的重点是:

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

我认为你的问题会得到解决。

享受!!!

答案 2 :(得分:1)

您可以使用以下方法设置更新间隔, 服务将每1分钟重新启动一次。:

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);
}