Android应用程序启动(根Activity)过程,跨平台app开发框架首选

  1. ActivityThread启动Activity

注意,该篇学习之前,要弄懂的知识:

  1. 系统的启动流程

按下电源键后,一个Android系统是怎么启动的。

主要涉及到 Init进程ZygoteSystemServerLauncher的知识概念

  1. 应用程序进程的启动过程

一个应用程序所在进程是怎么创建出来的。就是 Zygote的Socket启动一个死循环来等待AMS发来启动一个应用程序进程的请求

主要涉及到 ActivityManagerService(即AMS)创建Binder线程池创建消息循环的概念

网上有很多介绍上面东西的资料,最好跟着重点的源码过一遍,不然下面的内容也不知道在说什么。

下面的源码基于 Android8.0

1.Lanuncher请求AMS的过程

====================================================================================

我们知道Launcher是Android系统的第一个应用程序,它会读取 PakgesManagerService来获取当前系统装了哪些应用,并把这些应用程序的快捷图标展示在桌面上。

我们通过点击应用的快捷图标,就会通过Launcher请求AMS来启动该应用。我们来看看第一个大步骤的时序图:

在这里插入图片描述

阅读源码的正确方式就是先看一遍时序图,再读一遍重点源码,再回来看一遍时序图。

在我们点击应用程序的快捷图标时,就会调用Launcher的 startActivitySafely(),我们来看看这个方法的代码:

// launcher3/Launcher.java

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {

// 1

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

if (v != null) {

intent.setSourceBounds(getViewBounds(v));

}

try {

if (Utilities.ATLEAST_MARSHMALLOW

&& (item instanceof ShortcutInfo)

&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT

|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)

&& !((ShortcutInfo) item).isPromise()) {

// Shortcuts need some special checks due to legacy reasons.

startShortcutIntentSafely(intent, optsBundle, item);

} else if (user == null || user.equals(Process.myUserHandle())) {

// 2

startActivity(intent, optsBundle);

}

} catch (ActivityNotFoundException|SecurityException e) {

}

return false;

}

注释1:创建一个intent后把intent的Flag置为 FLAG_ACTIVITY_NEW_TASK,这个flag表示这个Activity会在新的任务栈中启动(像singleTask模式那样)。

一般来说,往下走,代码一般都会走到注释2的分支去。

注释2:传入intent,执行startAcivity()。这个方法在Activity.java类中实现,我们来看看其代码:

// Activity.java

@Override

public void startActivity(Intent intent, @Nullable Bundle options) {

if (options != null) {

startActivityForResult(intent, -1, options);

} else {

startActivityForResult(intent, -1);

}

}

都是走到 startActivityForResult()中去,其中第一个参数为在Launcher中创建的Intent,第二个参数-1表示Launcher不需要知道Activity启动的结果。也就是说Lancher只管发请求,之后怎么样就再也不处理了。我们来看看 startActivityForResult()的代码:

// Acitvity.java

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,

@Nullable Bundle options) {

// 1

if (mParent == null) {

options = transferSpringboardActivityOptions(options);

Instrumentation.ActivityResult ar =

mInstrumentation.execStartActivity(

this, mMainThread.getApplicationThread(), mToken, this,

intent, requestCode, options);

} else {

}

}

注释1:如果mParent==null 则往下走execStartActivity()

mParent是当前Activity的父类,因为根Activity还没有创建出来,所以mParent就是null。

接着调用 Instrumentation类的 execStartActivity(),传入参数:this(上下文)、但前应用主线程、token、this(上下文)、Launcher来的intent、requstCode(-1,表示无需知道后面的结果)、携带参数bundle。

接着我们来看看 Instrumentation这个类的启动Activity的方法:

public ActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, String target,

Intent intent, int requestCode, Bundle options) {

try {

intent.migrateExtraStreamToClipData();

intent.prepareToLeaveProcess(who);

int result = ActivityManager.getService()

.startActivity(whoThread, who.getBasePackageName(), intent,

intent.resolveTypeIfNeeded(who.getContentResolver()), //1

token, target, requestCode, 0, null, options);

checkStartActivityResult(result, intent); //2

} catch (RemoteException e) {

throw new RuntimeException(“Failure from system”, e);

}

return null;

}

try{}中,先修改一下intent的内容。

其次在注释1中:调用 ActivityManager.getService().startActivity()一套组合拳。

这条代码先从 ActivityManager.getService()获取AMS在Client端的代理对象。也就是说,它会返回个可以看做是 AMS的对象。

然后调用其 startActivity(),也就是调用 ASM.startActivity()

我们先不进入到AMS的startActivity去,而是看看这个 AMS是怎么来的。

在Android8.0之前,是通过 ActivityManagerNative.getDefaul()来获取AMS的代理对象的,现在这个逻辑放到了 ActivityManager中而不是 ActivityManagerNative中,在我之前做的笔记《Android艺术探索》这本书里面,用的是7.0的代码,可以看下面:

在这里插入图片描述

我们来看看getServcie的代码:

// AcitvityManager.java

public static IActivityManager getService() {

return IActivityManagerSingleton.get();

}

这个方法返回一个IActivityManager的对选哪个,有了解AIDL或代理模式的应该就能立马知道 IActivityManagerActivityManagerService在客户端的代理类!

我们来看看 IActivityManagerSingletonget()

// ActivityManager.java

private static final Singleton IActivityManagerSingleton =

new Singleton() {

@Override

protected IActivityManager create() {

//1

final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);

//2

final IActivityManager am = IActivityManager.Stub.asInterface(b);

return am;

}

};

注释1:从 ServiceManager得到一个IBinder,也就是 “IBinder类型的AMS”

注释2:将IBinder通过 asInterface()转换成一个 IActivityManager对象,通过get()可以得到这个对象。

上面是 AIDL的做法,用 进程间通信完成的从 客户端层到 服务端层的实现。8.0之前并不是AIDL的做法。至于AIDL的用法、原理网上已经有n多的blog去学习了。这里不再赘述。

至此,第一阶段结束,execStartActivity方法最终会调用到 ActivityManagerService.startActivity()

这部分其实特别好理解。

2.AMS到ApplicationThread的调用过程

=============================================================================================

在这里插入图片描述

可以看到,从AMS到ApplicaitonThread的过程就有些复杂了,图中会经过 ActivityStarterActivityStackSupervisorActivityStack这样的类。

我们先来看看最初始的 ActivityMangerService的startAcitivty方法:

// ActivityManagerService.java

@Override

public final int startActivity(IApplicationThread caller, String callingPackage,

Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {

return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,

resultWho, requestCode, startFlags, profilerInfo, bOptions,

UserHandle.getCallingUserId());

}

调用自己的 startActivityAsUser(),可以看到在参数的对比上,后者多了一个 getCallingUserId(),顾名思义,这个方法可以获取到调用者的UserId,AMS就是根据这个UserId来确定调用者的权限的:

@Override

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,

Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {

//1

enforceNotIsolatedCaller(“startActivity”);

//2

userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),

userId, false, ALLOW_FULL_ONLY, “startActivity”, null);

//3

return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,

resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,

profilerInfo, null, null, bOptions, false, userId, null, null,

“startActivityAsUser”);

}

每行代码都很重要:

注释1:判断调用者进程是否被隔离(是否可用),如果被隔离则抛出异常。

注释2:检查调用者是否有权限,是根据传进来的 userId进行判断的。如果没有权限也会抛出异常

注释3:调用 ActivityStarter.startActivityMayWait()

这里需要注意的是倒数第二个参数 TaskRecord,代表启动Activity所在的栈,最后一个参数reason,代表启动Activity的理由,我们来看看以下 startActivityMayWait()

// ActivityStarter.java

final int startActivityMayWait(IApplicationThread caller, int callingUid,

String callingPackage, Intent intent, … int userId,

IActivityContainer iContainer, TaskRecord inTask, String reason) {

int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,

aInfo, rInfo, voiceSession, voiceInteractor…, container,

inTask, reason);

return res;

}

}

ActivityStarter 是Android7.0中新加入的类,它是加载Activity的控制类

这个类的作用是根据传入的数据来吧Intent转换成Activity的。在这个方法里面,调用到了 startActivityLocked(),这个方法是通向后面启动Activity的方法,我们来看一下其源码:

// ActivityStarter.java

int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,

String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,

IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,

String callingPackage, int realCallingPid, int realCallingUid, int startFlags,

ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,

ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,

TaskRecord inTask, String reason) {

if (TextUtils.isEmpty(reason)) {

throw new IllegalArgumentException(“Need to specify a reason.”);

}

mLastStartReason = reason;

mLastStartActivityTimeMs = System.currentTimeMillis();

mLastStartActivityRecord[0] = null;

mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,

aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,

callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,

options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,

container, inTask);

return mLastStartActivityResult;

}

这个方法就是处理了一下为什么要创建Activity的Reason这个String。然后调用了 startActivity(),我们往下看:

private int startActivity(IApplicationThread caller…) {

int err = ActivityManager.START_SUCCESS;

final Bundle verificationBundle

= options != null ? options.popAppVerificationBundle() : null;

ProcessRecord callerApp = null;

//1

if (caller != null) {

//2

callerApp = mService.getRecordForAppLocked(caller);

if (callerApp != null) {

callingPid = callerApp.pid;

callingUid = callerApp.info.uid;

} else {

Slog.w(TAG, "Unable to find app for caller " + caller

  • " (pid=" + callingPid + ") when starting: "

  • intent.toString());

err = ActivityManager.START_PERMISSION_DENIED;

}

}

//3 这里创建即将要启动的Activity的描述类ActivityRecord。

ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,

callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),

resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,

mSupervisor, container, options, sourceRecord);

if (outActivity != null) {

outActivity[0] = r;

}

//4

return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,

options, inTask, outActivity);

}

注释1:判断IApplicationThread类型的caller是否为null,这个caller是方法调用一路传过来的,指向 Launcher所在应用程序进程的 ApplicationThread对象。

注释2:调用AMS的 getRecordForAppLocked()方得到一个 代表Launcher进程的 ProcessRecord类的实例callerApp。ProcessRecord用来描述一个应用程序进程。

注释3:同样的 ActivityRecord用来描述一个 Activity的所有信息。创建一个新的赋给r,然后r作为 outActivity第一个数据。

outActivity是 ActivityRecord[]类型的数据。

注释4:把这个方法里面得出的所有参数,传到重载方法 startActivity()中:

// ActivityStarter.java

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,

IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,

ActivityRecord[] outActivity) {

int result = START_CANCELED;

try {

mService.mWindowManager.deferSurfaceLayout();

//调用startActivityUnchecked

result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,

startFlags, doResume, options, inTask, outActivity);

}

return result;

}

这里返回 startActivityUnchecked()这个函数:

// ActivityStarter

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,

IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,

ActivityRecord[] outActivity) {

//1

if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask

&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {

newTask = true;

//2 创建新的TaskRecord

result = setTaskFromReuseOrCreateNewTask(

taskToAffiliate, preferredLaunchStackId, topStack);

} else if (mSourceRecord != null) {

result = setTaskFromSourceRecord();

} else if (mInTask != null) {

result = setTaskFromInTask();

} else {

setTaskToCurrentTopOrCreateNewTask();

}

if (mDoResume) {

final ActivityRecord topTaskActivity =

mStartActivity.getTask().topRunningActivityLocked();

if (!mTargetStack.isFocusable()

|| (topTaskActivity != null && topTaskActivity.mTaskOverlay

&& mStartActivity != topTaskActivity)) {

} else {

if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {

mTargetStack.moveToFront(“startActivityUnchecked”);

}

//3

mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,

mOptions);

}

}

startActivityUnchecked() 它的作用主要是处理与 栈管理相关的逻辑。所以这个方法就是我们新的Activity所处的栈的管理方法了。

注释1:由于我们传入进来的Intent的FLAG是有 FLAG_ACTIVITY_NEW_TASK这个属性的,所以能通过if

注释2:通过 setTaskFromReuseOrCreateNewTask,它会创建出一个 TaskRecord,前面说过,它用来描述一个任务栈,也是Activity最直观的表现类,之所以这么说,是因为任务栈是一个假象的模型,他实际并不存在,所以这个方法相当于创建了一个任务栈出来。

注释3:调用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(),这个方法从ActivityStarter深入到了ActivityStackSupervisor,是往下走的一个方法。

我们来看看这个方法:

// ActivityStackSupervisor

boolean resumeFocusedStackTopActivityLocked(

ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

if (targetStack != null && isFocusedStack(targetStack)) {

return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);

}

//1

final ActivityRecord r = mFocusedStack.topRunningActivityLocked();

//2

if (r == null || r.state != RESUMED) {

//3

mFocusedStack.resumeTopActivityUncheckedLocked(null, null);

} else if (r.state == RESUMED) {

mFocusedStack.executeAppTransition(targetOptions);

}

return false;

}

注释1:调用ActivityStack.topRunningActivityLocked()获取要启动的Activity所在栈的栈顶的不是处于停止状态的ActivityRecord

注释2:判断这个 ActivityRecord 是否为空或者要启动的Activity是不是 RE

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

浏览器打开:qq.cn.hn/FTe 免费领取

SUMED状态,由于我们是创建根Activity,所以这个 r 是空的。所以它会调用注释3的代码

注释3:调用 ActivityStack.resumeTopActivityUncheckedLocked,这个方法名虽然长,但是我们可以知道它大概的意思就是 启动一个栈顶Activity。我们来看看这个方法:

// ActivityStack

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {

boolean result = false;

try {

mStackSupervisor.inResumeTopActivity = true;

//1

result = resumeTopActivityInnerLocked(prev, options);

} finally {

mStackSupervisor.inResumeTopActivity = false;

}

mStackSupervisor.checkReadyForSleepLocked();

return result;

}

注释1:上面的代码在 try-catch里面,调用了 resumeTopActivityInnerLocked()去置result。

我们来看看这个方法:

// ActivityStack

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

mStackSupervisor.startSpecificActivityLocked(next, true, true);

}

}

因为这个方法代码非常多,所以我们来看它调用比较关键的代码就可以了,即调用了 ActivitySupervisor.startSpecificActivityLocked

回到了 ActivitySupervisor中,我们来看看这段代码:

// ActivitySupervisor

void startSpecificActivityLocked(ActivityRecord r,

boolean andResume, boolean checkConfig) {

// 1

ProcessRecord app = mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid, true);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值