onStartCommand返回值的区别
@IntDef(flag = false, prefix = { "START_" }, value = {
START_STICKY_COMPATIBILITY,
START_STICKY,
START_NOT_STICKY,
START_REDELIVER_INTENT,
})
START_STICKY_COMPATIBILITY
Service被杀死后会重启(执行了onCreate方法),但是onStartCommand方法没有被执行。
D/MyService: onCreate
D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1
D/MyService: startResult= 0 //START_STICKY_COMPATIBILITY
system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 1000ms for start-requested
system_process D/Boost: hostingType=service, hostingName={com.example.myapplication/com.example.myapplication.MyService}, callerPackage=com.example.myapplication, isSystem=false, isBoostNeeded=false.
system_process I/ActivityManager: Start proc 7675:com.example.myapplication/u0a270 for service {com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication
D/MyService: onCreate
START_STICKY
进程被杀后Service会被重启,执行onCreate和onStartCommand,重启后的Intent为null
MyService: onCreate
D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1
D/MyService: startResult= 1 // START_STICKY
system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 1000ms for start-requested
system_process D/Boost: hostingType=service, hostingName={com.example.myapplication/com.example.myapplication.MyService}, callerPackage=com.example.myapplication, isSystem=false, isBoostNeeded=false.
system_process I/ActivityManager: Start proc 4522:com.example.myapplication/u0a270 for service {com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication
D/MyService: onCreate
D/MyService: onStartCommand intent=null startId=2 // startID不一致,代表不是同一个实例,intent为null
D/MyService: startResult= 1
START_NOT_STICKY
进程被杀后Service不会被重启
D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1
D/MyService: startResult= 2 //START_NOT_STICKY
START_REDELIVER_INTENT
Service被杀死后会重启(执行了onCreate方法),并且onStartCommand方法会执行。从startId可以看出两个Service对象是同一个,并且onStartCommand方法中的intent和前一个intent值是一致的。
D/MyService: onCreate
D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1
D/MyService: startResult= 3
ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 17938ms for start-requested
system_process D/Boost: hostingType=service, hostingName={com.example.myapplication/com.example.myapplication.MyService}, callerPackage=com.example.myapplication, isSystem=false, isBoostNeeded=false.
system_process I/ActivityManager: Start proc 6307:com.example.myapplication/u0a270 for service {com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication
D/MyService: onCreate
D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1
D/MyService: startResult= 3
RestartService的流程
1、无须restart Service,直接bringDown的情况
- 非persistent进程crash次数达到16次
- 不允许自启Service
- Service的userId不在运行中
final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
......
for (int i=app.services.size()-1; i>=0; i--) {
ServiceRecord sr = app.services.valueAt(i);
......
// Any services running in the application may need to be placed
// back in the pending list.
if (allowRestart && sr.crashCount >= mAm.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
&& (sr.serviceInfo.applicationInfo.flags
&ApplicationInfo.FLAG_PERSISTENT) == 0) {
// 若进程crash次数大于等于16次,且为非persistent进程,则直接bringDown Service
bringDownServiceLocked(sr);
} else if (!allowRestart|| !mAm.mUserController.isUserRunning(sr.userId, 0)) {
// 若不允许重启或当前userId不在运行,则直接bringDown Service
bringDownServiceLocked(sr);
} else {
// 直接计划Service的重启,成功返回true,否则返回false
boolean canceled = scheduleServiceRestartLocked(sr, true);
// start方式启动,且以下两种满足一种
// 1.app的onStartCommand方法返回值不是sticky的
// 2.计划restart 被取消
// 且Service没有pending start ,会将Service的startRequested置为false,这种情况会导致isServiceNeededLocked为false,restartService失败
// stopIfKilled 由onStartCommand返回值决定
if (sr.startRequested && (sr.stopIfKilled || canceled)) {
if (sr.pendingStarts.size() == 0) {
sr.startRequested = false;
......
// 如果Service没有AutoCreate相关的Connections,则会直接bringDown Service
if (!sr.hasAutoCreateConnections()) {
// Whoops, no reason to restart!
bringDownServiceLocked(sr);
}
}
}
}
}
}
2、restartService被取消的情况
可以通过调用unscheduleServiceRestartLocked方法来取消restart service,取消
- bringDownServiceLocked 在killServicesLocked时会有
- startServiceLocked
- bindServiceLocked
3、restartService成功的情况
killServicesLocked时如果条件满足,会通过scheduleServiceRestartLocked去post ServiceRestarter到MainHandler里,当run方法被执行时会去调用performServiceRestartLocked
此时回去再次校验是否需要重启,如下情况可以重启
-
Service有AutoCreate的Connections 非Start方式启动
-
onStartCommand返回值为START_STICKY_COMPATIBILITY或START_STICKY
-
Service的pendingStarts不为空
final void performServiceRestartLocked(ServiceRecord r) {
// Service会在scheduleServiceRestartLocked方法中添加到mRestartingServices列表中
if (!mRestartingServices.contains(r)) {
return;
}
if (!isServiceNeededLocked(r, false, false)) {
Slog.wtf(TAG, "Restarting service that is not needed: " + r);
return;
}
......
}
private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn) {
// start方式启动的话得看onStartcommand的返回值以及是否有pending starts,startReuested是有可能为false的。
if (r.startRequested) {
return true;
}
// Is someone still bound to us keeping us running?
if (!knowConn) {
hasConn = r.hasAutoCreateConnections();
}
if (hasConn) {
return true;
}
return false;
}