前言
Activity
类是 android 应用的关键组件,在日常开发中,绝对少不了组件。既然用了这么久,你知道他的启动流程🐴?作为一个应用层开发者,大多数人可能觉得学习这些对日常开发可能没有太大帮助。但是多了解一下 framework 的代码还是很有必要的,了解系统组件机制,对于一些问题我们也能快速的定位找到问题的所在点,并且在面试的时候也是一个加分项。
本文基于 Android 12 版本源码,从 startActivity
作为切入点,对整个启动流程进行分析。
Activity 启动方式
启动一个 Activity,通常有两种情况,一种是在应用内部启动 Activity,另一种是 Launcher 启动。
- 应用内启动 通过 startActivity 来启动 Activity
- Launcher 进程启动 Launcher 就是我们桌面程序,当系统开机后, Launcher 也随之被启动,然后将已经安装的 app 显示在桌面上,等到点击某一个 app 的时候就会 fock 一个新的进程,然后启动 Activity
这篇文章主要来看一下应用内启动 Activity 是一个怎样的流程
一,Activity -> ATMS
众所周知,一般情况下Activity 的启动方式有下面种:
- startActivity(Intent intent):直接启动一个 Activity
- startActivityForResult(Intent intent, int requestCode):带返回值的启动方式,这种启动方式已经被官方所废弃,取而代之的是
registerForActivityResult(contract, mActivityResultRegistry, callback)
我们从 startActivity 来一步步往下看:
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
......
//execStartActivity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
//分析启动结果
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
......
} else {
if (options != null) {
//这里最终也是调用 execStartActivity 方法
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
上面代码中,调用了 execStartActivity 方法,该方法会返回一个启动结果。最下面的的 startActivityFromChild 方法最终也是调用的 execStartActivity。
我们先看一下该方法的参数:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
}
Context who :传入的是 this,用来启动 Activity 的对象
Ibinder contextThread:Binder 对象,具有跨进程通信的能力,传入的是 mMainThread.getApplicationThread()
public ApplicationThread getApplicationThread(){
return mAppThread;
}
final ApplicationThread mAppThread = new ApplicationThread();
private class ApplicationThread extends IApplicationThread.Stub {
.....
}
ApplicationThread 是 Activitythread 的内部类,就是通过 AIDL 创建的一个远程服务的接口,用来与服务端进行交互,该对象会被传入到 AMS 中,在 AMS 中回保存他的 client(客户端),这样 AMS 就可以与应用进程进行通信了
IBinder token:Binder 对象,指向了服务端一个 ActivityRecord 对象
Activity target:当前的 Activity
Intent intent, int requestCode, Bundle options :Intent 对象,请求码和参数。
下面我们来看一下 execStartActivity
方法:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//应用端 AIDL 实现类
IApplicationThread whoThread = (IApplicationThread) contextThread;
.......
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
//通过 Binder 调用 ATMS 启动 Activity
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
//获取单例
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
我们可以用一张图来表示上述的流程:
image-20221221164643149
上面代码中通过 getService
获取到 Binder 对象,然后将 Binder 转成 AIDL 接口所属的类型,接着就可以调用 AIDL 中的方法与服务端进行通信了。
接着调用 ATMS 中的 startActivity()
方法发起启动 Activity 请求,获得启动结果 result。在调用 checkStartActivityResult
方法,传入 result,来判断能否启动 Activity,不能启动就会抛出异常,例如 activity 未在 manifest 中声明等。
二 、ATMS
通过上面的代码可以看出已经调用到了系统的 ATMS 当中,我们来看一下具体的流程
#ActivityTaskManagerService.java
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
#ActivityTaskManagerService.java
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
#ActivityTaskManagerService.java
private int startActivityAsUser(IApplicationThread caller,