通过上一篇文章我们掌握了Android四种的基本使用,本篇从源码层面总结一下startService的执行过程。
本文依然按着是什么?有什么?怎么用?啥原理?的步骤来分析。
1、是什么
上一篇总结了“Service是Android系统中的四大组件之一,它是一种没有可视化界面,运行于后台的一种服务程序。属于计算型组件,用来在后台执行持续性的计算任务,重要性仅次于Activity活动”。
2、有什么
Service和Activity一样也有自己的生命周期,也需要在AndroidManifest.xml中注册。
2.1 在AndroidManifest.xml中注册
<service android:name="com.example.testdemo.service.ServiceJia" />
2.2 Service生命周期
Service的生命周期有很多,本文只谈startService和stopService涉及到的。
onCreate
它只在Service刚被创建的时刻被调用,Service在运行中,这个方法将不会被调用。也就是只有经历过onDestroy生命周期以后再次startService(intent) 才会执行。
onStartCommand
OnStartCommand方法是最重要的方法,因为它在我们需要启动Service的时候被调用。形参时当初startService时传递进来的Intent,这样就可以给Service传值。在这个方法中,可以做服务启动后要执行的任务,但是切记这里也是在主线程运行,耗时的操作必须创建一个子线程来执行,否则可能引发ANR导致程序闪退。
关于onStartCommand的返回值介绍:
START_STICKY:此时Service被杀死以后将会被重新创建。但是不会重新传入原来的Intent对象,而是传入intent为null。
START_NOT_STICKY:此时Service被杀死以后不会被重新创建。
START_REDELIVER_INTENT:功能与START_STICKY类似在Service被杀死以后将会被重新创建。厉害的一点时,该返回值时Intent会重新传递给Service。
onDestroy
onDestory是在Service即将被销毁时执行的生命名周期,Service和Activity生命周期不一样,Service没有onStop生命周期。
日志打印:
调用startService后的生命周期:
2024-07-01 10:20:59.756 20505-20505/com.example.testdemo3 E/com.example.testdemo3.service.ServiceJia: onCreate:
2024-07-01 10:20:59.757 20505-20505/com.example.testdemo3 E/com.example.testdemo3.service.ServiceJia: onStartCommand:
调用stopService后的生命周期:
2024-07-01 10:21:06.861 20505-20505/com.example.testdemo3 E/com.example.testdemo3.service.ServiceJia: onDestroy:
- 怎么用
关于使用方法上一篇已经总结,这里不在赘述。
4、啥原理
Service的启动方法是调用
Intent serviceIntent = new Intent(ServiceActivity.this, ServiceJia.class);
startService(serviceIntent);
然后我们顺着startService方法开始解析源码,SDK版本API 30:
4.1 从ContexWrapper的startService开始:
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
4.2 ContextImpl类startService
mBase的类型是Context,但实际代码逻辑是在它的实现类ContextImpl类。
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
//
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
} else if (cn.getPackageName().equals("?")) {
throw new IllegalStateException(
"Not allowed to start service " + service + ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在ContextImpl类的startService中调用了startServiceCommon方法,而其中的关键代码是ActivityManager.getService().startService方法调用。
4.3 来到ActivityManager类
/**
* @hide
*/
@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
具体实现是在ActivityManagerService.java
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, callingFeatureId, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
4.4 进入ActiveServices类,用来辅助ActivityServiceManager管理Service的启动和停止等。
mServices = new ActiveServices(this);
上面先调用ActiveServices的startServiceLocked方法;
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, callingFeatureId, userId);
然后startServiceLocked又调用本类的startServiceInnerLocked方法:
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
然后startServiceInnerLocked又调用本类的bringUpServiceLocked方法:
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
然后在调用bringUpServiceLocked方法realStartServiceLocked:
realStartServiceLocked(r, app, execInFg);
4.5调用ApplicationThread的scheduleCreateService方法
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
之后调用了sendServiceArgsLocked(r, execInFg, true);他就是onStartCommand生命周期,此处伏笔,下面4.8中详聊。
4.6 进入ApplicationThread类:
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
这里sendMessage方法不是Handler的哈,是封装以后的,继续看:
void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) {
Slog.v(TAG,
"SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
}
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
4.7 这里发送了消息,然后去找对应what = H.CREATE_SERVICE的处理:
在handleMessage方法中处理:
case CREATE_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
}
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
关键时刻来咯:
@UnsupportedAppUsage
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
Application app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// Service resources must be initialized with the same loaders as the application
// context.
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
这里先创建了一个ContextImpl实例,然后创建了Application(这里是个工厂模式等于空了才创建);创建Service实例并与ContextImpl关联;然后调用onCreate的生命周期方法。最后有个mServices.put,后面其他场景会从里面取来使用。
4.8再看onStartCommand生命周期
先生是否记得上面4.4小节买过伏笔sendServiceArgsLocked(r, execInFg, true);
sendServiceArgsLocked的r.app.thread.scheduleServiceArgs(r, slice);这行代码很熟悉了,和调用onCreate时候是一样的模式。
进入ApplicationThread类:
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = ssa.taskRemoved;
s.startId = ssa.startId;
s.flags = ssa.flags;
s.args = ssa.args;
sendMessage(H.SERVICE_ARGS, s);
}
}
二次封装的发消息:
sendMessage(H.SERVICE_ARGS, s);和onCreate一样。
handleMessage处理消息:
case SERVICE_ARGS:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceStart: " + String.valueOf(msg.obj)));
}
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
从mServices取出onCreate是存的service,然后调用onStartCommand生命周期。
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
至此StartService的启动该流程分析完毕!
才疏学浅,如有错误,欢迎指正,多谢。