Service重启流程

本文档适合对Service的启动和停止的fwk流程有一定了解的查看。

基础知识

ServiceRecord

    boolean fgRequired;     // 是否请求的是前台Service,完成后设置为false。
    boolean startRequested; //  是否是start方式启动,在start权限校验后才会赋值为true,Service stop后会赋值为false
    boolean isForeground;   // 当前Service是否是前台Service,startForeground后赋值为true,stopForeground赋值为false
    boolean stopIfKilled;   // 跟onStartCommand返回值有关,START_STICKY_COMPATIBILITY/START_STICKY等为false;表示Service被杀后是否停止重启;
    boolean callStart;      //  决定Service重启后是否执行onStartCommand,START_STICKY_COMPATIBILITY时会赋值为false
    int crashCount;         // number of times proc has crashed with service running

    int restartCount;       // 连续执行的重启次数
    long restartDelay;      // 下一次重启的delay,scheduleServiceRestartLocked 赋值,启动/停止/绑定时会重置为0
    long restartTime;       //上次调用realStartServiceLocked的时间
    long nextRestartTime;   // 当前时间+restartDelay
    int totalRestartCount;  // 不得不重启的次数

    final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>(); // 在sendServiceArgsLocked中会添加StartItem到这个列表中,执行完serviceDoneExecutingLocked/或stop后会从该列表中移除,返回值为START_REDELIVER_INTENT时不会从列表中移除.
    final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>(); // startServiceInnerLocked时添加进列表,sendServiceArgsLocked 中移除; 

StartItem

        long deliveredTime; // 在sendServiceArgsLocked中赋值,START_REDELIVER_INTENT返回值时,重启时会根据这个计算延时时间
        int deliveryCount;  // 调用一次 sendServiceArgsLocked增加一次计数,如果onStartCommand执行失败的次数超过两次,后面就不会为这个intent重发,主要针对START_REDELIVER_INTENT
        int doneExecutingCount;  //如果返回START_REDELIVER_INTENT时,则该引用计数+1

Service重启时序图

在这里插入图片描述

常见问题问答

什么情况下进程被杀后Service能重启?

  1. start方式启动时onStartCommand返回值是START_STICKY_COMPATIBILITY/START_STICKY/START_REDELIVER_INTENT之一
  2. Servive有flag是BIND_AUTO_CREATE的连接
  3. 进程被杀时Service还没执行完onStartCommand方法,导致deliverStarts中的额StartItem没有被移除
    boolean canStopIfKilled(boolean isStartCanceled) {
    
    
        // onStartCommand返回值是START_STICKY_COMPATIBILITY/START_STICKY时,stopIfKilled为false;
        //  onStartCommand返回值是START_REDELIVER_INTENT时,这里的pendingStarts不为空
        return startRequested && (stopIfKilled || isStartCanceled) && pendingStarts.isEmpty();
    }

// Servive有flag是BIND_AUTO_CREATE的连接
    public boolean hasAutoCreateConnections() {
    
    
        for (int conni=connections.size()-1; conni>=0; conni--) {
    
    
            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
            for (int i=0; i<cr.size(); i++) {
    
    
                if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
    
    
                    return true;
                }
            }
        }
        return false;
    }
    /** @return {@code true} if the restart is scheduled. */
    private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {
    
    
            .......
            if (allowCancel) {
    
    
                // start方式启动,返回值是START_STICKY_COMPATIBILITY/START_STICKY/START_REDELIVER_INTENT之一时,shouldStop为false
                final boolean shouldStop = r.canStopIfKilled(canceled);
                if (shouldStop && !r.hasAutoCreateConnections()) {
    
    
                    // Nothing to restart.
                    return false;
                }
                reason = (r.startRequested && !shouldStop) ? "start-requested" : "connection";
            } else {
    
    
                reason = "always";
            }

       .......
        return true;
    }

onStartCommand不同返回值有什么不同的效果?


@IntDef(flag = false, prefix = {
    
     "START_" }, value = {
    
    
        START_STICKY_COMPATIBILITY, // 重启后只执行onCreate
        START_STICKY, // 重启后执行onCreate、onStartCommand,但intent为null
        START_NOT_STICKY, // 不重启
        START_REDELIVER_INTENT, //重启后执行onCreate、onStartCommand、intent不为null、onStartCommand可能执行多次,重启delay时间较长。
})

START_NOT_STICKY

进程被杀后Service不会被重启 : 因为这里stopIfKilled赋值为true。

    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,
            boolean enqueueOomAdj) {
    
    
        boolean inDestroying = mDestroyingServices.contains(r);
        if (r != null) {
    
    
            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
    
    
                // This is a call from a service start...  take care of
                // book-keeping.
                // 表明默认重启后需要回调onStartCommand方法
                r.callStart = true;
                switch (res) {
    
    
                   ......
                    case Service.START_NOT_STICKY: {
    
    
                        // 查找并将当前StartItem从deliveredStarts列表中移除
                        r.findDeliveredStart(startId, false, true);
                        if (r.getLastStartId() == startId) {
    
    
                            // There is no more work, and this service
                            // doesn't want to hang around if killed.
                            r.stopIfKilled = true;
                        }
                        break;
                    }
            ......
            }.......
    }

START_STICKY_COMPATIBILITY

Service被杀死后会重启(执行了onCreate方法),但是onStartCommand方法没有被执行。

system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 1000ms for start-requested
system_process I/ActivityManager: Start proc 7675:com.example.myapplication/u0a270 for service {
    
    com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication
com.example.myapplication D/MyService: onCreate
    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,
            boolean enqueueOomAdj) {
    
    
        boolean inDestroying = mDestroyingServices.contains(r);
        if (r != null) {
    
    
            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
    
    
                // This is a call from a service start...  take care of
                // book-keeping.
                r.callStart = true;
                switch (res) {
    
    
                    case Service.START_STICKY_COMPATIBILITY:
                    case Service.START_STICKY: {
    
    
                        // We are done with the associated start arguments.
                        // 查找并将当前StartItem从deliveredStarts列表中移除
                        r.findDeliveredStart(startId, false, true);
                        // Don't stop if killed.
                        r.stopIfKilled = false;
                        break;
                    }
                 .......
                }
                // 这里callStart赋值为false, 决定Service重启后不执行onStartCommand方法。
                if (res == Service.START_STICKY_COMPATIBILITY) {
    
    
                    r.callStart = false;
                }
            }.......
    }
    private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
            IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
            boolean enqueueOomAdj) throws RemoteException {
    
    
        ......
        // callStart为false,则StartItem不会添加到pendingStarts列表;sendServiceArgsLocked方法中传递到app端的ServiceStartArgs列表会为空,导致不会遍历执行到onStartCommand方法
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
    
    
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null, 0));
        }
        // 从这个方法中会触发app端回调Service的onStartCommand方法
        sendServiceArgsLocked(r, execInFg, true);
        .......
    }

START_STICKY

进程被杀后Service会被重启,执行onCreate和onStartCommand,重启后的Intent为null。
具体代码同START_STICKY_COMPATIBILITY。

com.example.myapplication D/MyService: onCreate
com.example.myapplication D/MyService: onStartCommand intent=Intent {
    
     cmp=com.example.myapplication/.MyService (has extras) } startId=1
com.example.myapplication D/MyService: startResult= 1
system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 1000ms for start-requested
system_process I/ActivityManager: Start proc 4522:com.example.myapplication/u0a270 for service {
    
    com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication
com.example.myapplication D/MyService: onCreate
com.example.myapplication D/MyService: onStartCommand intent=null startId=2 // startID不一致,代表不是同一个实例,intent为null
com.example.myapplication D/MyService: startResult= 1

START_REDELIVER_INTENT

Service被杀死后会重启(执行了onCreate方法),并且onStartCommand方法会执行。从startId可以看出两个Service对象是同一个,并且onStartCommand方法中的intent和前一个intent值是一致的。

com.example.myapplication D/MyService: onCreate
com.example.myapplication D/MyService: onStartCommand intent=Intent {
    
     cmp=com.example.myapplication/.MyService (has extras) } startId=1
com.example.myapplication D/MyService: startResult= 3
system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 17938ms for start-requested
system_process I/ActivityManager: Start proc 6307:com.example.myapplication/u0a270 for service {
    
    com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication
com.example.myapplication D/MyService: onCreate
com.example.myapplication D/MyService: onStartCommand intent=Intent {
    
     cmp=com.example.myapplication/.MyService (has extras) } startId=1
com.example.myapplication D/MyService: startResult= 3
    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,
            boolean enqueueOomAdj) {
    
    
        boolean inDestroying = mDestroyingServices.contains(r);
        if (r != null) {
    
    
            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
    
    
                // This is a call from a service start...  take care of
                // book-keeping.
                r.callStart = true;
                switch (res) {
    
    
                   ......
                    case Service.START_REDELIVER_INTENT: {
    
    // 这个返回值,执行完Service的onStartCommand方法后,不会从deliverStarts列表中移除当前的StartItem,Service重启时会遍历deliverStarts列表,并将该列表中item添加到pendingStarts
                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false);
                        if (si != null) {
    
    
                            // 赋值为0,非0的话则表示app端的onStartCommand方法未正常执行
                            si.deliveryCount = 0;
                            // 标明该StartItem的执行成功的次数
                            si.doneExecutingCount++;
                            r.stopIfKilled = true;
                        }
                        break;
                    }
              .......
            }.......
    }
    private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {
    
    
       .......
           // 非persistent app才会判断重不重启,persistent app直接重启
        if ((r.serviceInfo.applicationInfo.flags
                &ApplicationInfo.FLAG_PERSISTENT) == 0) {
    
    
         ......
            final int N = r.deliveredStarts.size();
            // 针对START_REDELIVER_INTENT返回值,deliveredStarts不为空; 也有可能是进程被杀后onStartCommand方法还没执行完。
            if (N > 0) {
    
    
                for (int i=N-1; i>=0; i--) {
    
    
                    ServiceRecord.StartItem si = r.deliveredStarts.get(i);
                    si.removeUriPermissionsLocked();
                    if (si.intent == null) {
    
    
                        // We'll generate this again if needed.
                        // 同一个StartItem重启失败<3次或成功<6次才会继续重启
                    } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT //3
                            && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
    
     //6
                        // 将列表中item添加到pendingStarts
                        r.pendingStarts.add(0, si);
                        long dur = SystemClock.uptimeMillis() - si.deliveredTime;
                        dur *= 2;
                        // minDuration和resetTime赋值,一般是当前时间到deliver的时间间隔(下面称作devliver Duration),所以重启delay时间会很长,超过1s。
                        if (minDuration < dur) minDuration = dur;
                        if (resetTime < dur) resetTime = dur;
                    } else {
    
    
                        // 否则直接取消重启
                        Slog.w(TAG, "Canceling start item " + si.intent + " in service "
                                + r.shortInstanceName);
                        canceled = true;
                    }
                }
                // 清空Service的deliveredStarts的列表
                r.deliveredStarts.clear();
            }

Bind情况下如何重启?

Service有BIND_AUTO_CREATE的连接

com.example.testapplication D/MainActivity: flags= 1
com.example.myapplication D/MyService2: onCreate
com.example.myapplication D/MyService2: onBind
com.example.testapplication D/MainActivity: onServiceConnected
com.example.testapplication D/MainActivity: onServiceDisconnected
ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService2 in 10043ms for connection
ActivityManager: Start proc 10102:com.example.myapplication:remote/u0a253 for service {
    
    com.example.myapplication/com.example.myapplication.MyService2} caller=com.example.testapplication
com.example.myapplication D/MyService2: onCreate
com.example.myapplication D/MyService2: onBind
com.example.testapplication D/MainActivity: onServiceConnected

先bindService再startService

com.example.myapplication D/MyService2: onCreate
com.example.myapplication D/MyService2: onBind
com.example.myapplication D/MyService2: onStartCommand
com.example.testapplication D/MainActivity: onServiceConnected
com.example.testapplication D/MainActivity: onServiceDisconnected
system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService2 in 1000ms for start-requested
system_process I/ActivityManager: Start proc 13953:com.example.myapplication:remote/u0a253 for service {
    
    com.example.myapplication/com.example.myapplication.MyService2} caller=com.example.myapplication
com.example.myapplication D/MyService2: onCreate
com.example.myapplication D/MyService2: onBind
com.example.testapplication D/MainActivity: onServiceConnected
com.example.myapplication D/MyService2: onStartCommand

重启时间如何计算?

首次重启

  1. 如果是START_REDELIVER_INTENT返回值,重启delay时间一般为 (当前时间 - 上次deliver时间)*2,这个时间一般较长。
  2. 其它重启时间为1s。

app发生过crash

重启delay时间为1800s*(crashCount -1)

非首次重启

  1. START_REDELIVER_INTENT返回值, 当前时间距离上次重启 > 60s(或deliverDuration) ,则重启delay一般为deliverDuration;否则重启delay*60s。
  2. 其它,当前时间距离上次重启 > 60s,则重启delay为1s,否则delay * 60s。

最后需要保证两个重启的Service时间间隔不得<10s

    /** @return {@code true} if the restart is scheduled. */
    private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {
    
    
        ......
        final long now = SystemClock.uptimeMillis();

        final String reason;
        if ((r.serviceInfo.applicationInfo.flags
                &ApplicationInfo.FLAG_PERSISTENT) == 0) {
    
    
            long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION; //1s
            long resetTime = mAm.mConstants.SERVICE_RESET_RUN_DURATION; //60s
            boolean canceled = false;
            ........
            // 第一次重启
            if (r.restartDelay == 0) {
    
    
                r.restartCount++;
                r.restartDelay = minDuration;
                // crash重启时间为1800s * n
            } else if (r.crashCount > 1) {
    
    
                r.restartDelay = mAm.mConstants.BOUND_SERVICE_CRASH_RESTART_DURATION
                        * (r.crashCount - 1);
            } else {
    
    
                // 如果这次重启距离上次重启>60s(或者deliverDuration),重置delay为minDuration(非Deliver一般为1s)
                if (now > (r.restartTime+resetTime)) {
    
    
                    r.restartCount = 1;
                    r.restartDelay = minDuration;
                } else {
    
    
                    // 如果重启后很快又被杀,则delay需要* 60s的系数,增大重启延时
                    r.restartDelay *= mAm.mConstants.SERVICE_RESTART_DURATION_FACTOR;
                    if (r.restartDelay < minDuration) {
    
    
                        r.restartDelay = minDuration;
                    }
                }
            }

            if (isServiceRestartBackoffEnabledLocked(r.packageName)) {
    
    
                // 计算下次重启时间
                r.nextRestartTime = now + r.restartDelay;

                // Make sure that we don't end up restarting a bunch of services
                // all at the same time.
                boolean repeat;
                final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; //10s
                do {
    
    
                    // 避免一次重启太多的Service,至少保证10s的时间间隔
                    repeat = false;
                    for (int i = mRestartingServices.size() - 1; i >= 0; i--) {
    
    
                        final ServiceRecord r2 = mRestartingServices.get(i);
                        if (r2 != r
                                && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween)
                                && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) {
    
    
                            r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
                            r.restartDelay = r.nextRestartTime - now;
                            repeat = true;
                            break;
                        }
                    }
                } while (repeat);
            } else {
    
    
              
                // It's been forced to ignore the restart backoff, fix the delay here.
                r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION;
                r.nextRestartTime = now + r.restartDelay;
            }

        } else {
    
    
            // Persistent processes are immediately restarted, so there is no
            // reason to hold of on restarting their services.
            // persistent app立刻被拉起
            r.totalRestartCount++;
            r.restartCount = 0;
            r.restartDelay = 0;
            r.nextRestartTime = now;
            reason = "persistent";
        }

        if (!mRestartingServices.contains(r)) {
    
    
            r.createdFromFg = false;
            mRestartingServices.add(r);
            synchronized (mAm.mProcessStats.mLock) {
    
    
                r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
            }
        }

        cancelForegroundNotificationLocked(r);
        // 开始shedule重启
        performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis());
        return true;
    }

如何规避非预期的Service重启

背景

一键清理时会先执行removeTask操作,未添加FLAG_STOP_WITH_TASK flag的Service会触发执行一次onStartCommand方法,且在sendServiceArgsLocked中执行完后将新创建的StartItem从pendingStarts列表移动到deliveredStarts列表。这时候再执行杀进程会导致app端未能及时告知system server端执行serviceDoneExecutingLocked方法去移除deliveredStarts中的StartItem,导致进程被杀后还会立刻通过Service拉起来。

10-12 15:52:22.108 2489 3967 I ProcessManager: OneKeyClean: kill com.miui.huanji:backup Adj=100 State=4
10-12 15:52:22.122 2489 3967 I ProcessManager: OneKeyClean: kill com.miui.huanji Adj=50 State=4
10-12 15:52:22.144 2489 7247 W ActivityManager: Scheduling restart of crashed service com.miui.huanji/.backup.BackupService in 1000ms for connection

10-12 15:52:22.292 2489 7443 W ActivityManager: Scheduling restart of crashed service com.miui.huanji/.scanner.ScannerService in 50853ms for start-requested

代码逻辑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A0unfNiB-1657187467240)(https://cdn.nlark.com/yuque/__puml/ea3c0bcaa8932b38c2f5158d7cb6f5aa.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJcbmF1dG9udW1iZXJcbnNraW5wYXJhbSBzZXF1ZW5jZUFycm93VGhpY2tuZXNzIDJcbnNraW5wYXJhbSBoYW5kd3JpdGUgdHJ1ZSBcbnNraW5wYXJhbSByb3VuZGNvcm5lciAyMFxuc2tpbnBhcmFtIG1heG1lc3NhZ2VzaXplIDIwXG5za2lucGFyYW0gYmFja2dyb3VuZENvbG9yICMwZjE5MmFcbnNraW5wYXJhbSBoYW5kd3JpdGUgdHJ1ZVxuc2tpbnBhcmFtIHNlcXVlbmNlIHtcbkFycm93Q29sb3IgI2U4ZWFlY1xuQXJyb3dGb250Q29sb3IgI2U4ZWFlY1xuQXJyb3dGb250U2l6ZSAxNVxuTGlmZUxpbmVCb3JkZXJDb2xvciAjZThlYWVjXG5MaWZlTGluZUJhY2tncm91bmRDb2xvciAjZThlYWVjXG5QYXJ0aWNpcGFudEJvcmRlckNvbG9yICNlOGVhZWNcblBhcnRpY2lwYW50QmFja2dyb3VuZENvbG9yICNlOGVhZWNcblBhcnRpY2lwYW50Rm9udENvbG9yICMwZjE5MmFcbn1cblNvbW9uZSAtPiBBY3Rpdml0eVRhc2tTdXBlcnZpc29yIDogcmVtb3ZlVGFza1xuQWN0aXZpdHlUYXNrU3VwZXJ2aXNvciAtPiBBY3Rpdml0eVRhc2tTdXBlcnZpc29yIDogY2xlYW5VcFJlbW92ZWRUYXNrTG9ja2VkXG5BY3Rpdml0eVRhc2tTdXBlcnZpc29yIC0-IEFNUy5Mb2NhbFNlcnZpY2UgOiBjbGVhblVwU2VydmljZXNcbiBBTVMuTG9jYWxTZXJ2aWMgLT4gQWN0aXZlU2VydmljZXMgOiBjbGVhblVwU2VydmljZXNcbkFjdGl2ZVNlcnZpY2VzIC0-IEFjdGl2ZVNlcnZpY2VzIDogc2VuZFNlcnZpY2VBcmdzTG9ja2VkIiwidXJsIjoiaHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlL19fcHVtbC9lYTNjMGJjYWE4OTMyYjM4YzJmNTE1OGQ3Y2I2ZjVhYS5zdmciLCJpZCI6InNJaEJWIiwibWFyZ2luIjp7InRvcCI6dHJ1ZSwiYm90dG9tIjp0cnVlfSwiY2FyZCI6ImRpYWdyYW0ifQ==)]

    void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {
    
    
        ArrayList<ServiceRecord> services = new ArrayList<>();
        ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(userId);
        for (int i = alls.size() - 1; i >= 0; i--) {
    
    
            ServiceRecord sr = alls.valueAt(i);
            if (sr.packageName.equals(component.getPackageName())) {
    
    
                services.add(sr);
            }
        }

        // Take care of any running services associated with the app.
        boolean needOomAdj = false;
        for (int i = services.size() - 1; i >= 0; i--) {
    
    
            ServiceRecord sr = services.get(i);
            if (sr.startRequested) {
    
    
                if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
    
    
                    Slog.i(TAG, "Stopping service " + sr.shortInstanceName + ": remove task");
                    needOomAdj = true;
                    stopServiceLocked(sr, true);
                } else {
    
    
                    // 让app端触发onTaskRemoved方法
                    sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
                            sr.getLastStartId(), baseIntent, null, 0));
                    if (sr.app != null && sr.app.getThread() != null) {
    
    
                        // We always run in the foreground, since this is called as
                        // part of the "remove task" UI operation.
                        try {
    
    
                            sendServiceArgsLocked(sr, true, false);
                        } catch (TransactionTooLargeException e) {
    
    
                            // Ignore, keep going.
                        }
                    }
                }
            }
        }
        if (needOomAdj) {
    
    
            mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
        }
    }

解决方案

后期cleanUpService是异步执行的不会有这个问题(即杀进程会在cleanUpServices之前,没有Service会被遍历到),当时让app在功能清单文件中配置android.R.attr#stopWithTask。

Service重启三千问

  1. 什么情况下进程被杀后Service能重启?Start方式和bind方式的区别?
  2. onStartCommand返回值START_STICKY_COMPATIBILITY/START_STICKY和START_REDELIVER_INTENT实现Service重启 有什么区别?
  3. onStartCommand不同返回值有什么不同的效果?
  4. 什么返回值Service重启后不执行onStartCommand?
  5. 什么返回值Service重启不用重新发送intent?
  6. 哪些情况下Service会被更快的重启?
  7. START_REDELIVER_INTENT 重启时app的Service会执行几次onStartCommand?
  8. start方式启动的Service的stopIfKilled为true时,Service一定不可以重启么?
  9. deliveredStarts 什么时候添加?什么时候移除?
  10. pendingStarts 什么时候添加?什么时候移除?
  11. Service重启的restartDelay的计算逻辑?
  12. 什么情况下START_REDELIVER_INTENT返回值不再执行重启?

参考文档:https://www.jianshu.com/p/7a659ca38510

猜你喜欢

转载自blog.csdn.net/xiaoyantan/article/details/125664207