activity启动流程

今天要分析下fwk中activity的启动流程,之前看别人画的流程图,总是很快就忘记了,而且总是摸不着重点,遇到具体问题时还是不知道从何入手,又得从头看起。后来我想通了一件事,我们在分析这种源码时不应该过渡纠结于流程图与某个具体函数,而应该从宏观角度想想:要实现这个功能,他应该要包含哪些步骤?

学习activity启动流程时,请带着这样几个问题去阅读源码:

  1. 新的activity是何时被创建的?进程内启动activity与启动一个新进程过程有什么区别?
  2. 启动activity时,当前的activity应该是要进到后台的,那这个时间顺序是怎样的?这几个activity的顺序由谁来管理?
  3. 启动过程中的切换动画是什么时候调用的?activity启动后activity、window、application是什么时候绑定在一起的?

这几个问题的答案见我下面的标红部分,希望能有助于大家在遇到实际问题时,能直接定位到相关节点去分析,节省时间。

目录

具体流程

相关类简介


具体流程

整个流程可以分为两大步骤:启动前准备与真正启动。

  1. 启动前准备:在ActivityStarter和ActivityStackSupervisor 类中完成当前activity的暂停,并通知新的Activity的启动;(涉及Intent解析,activity在栈中的进出。旧Activity.onPause--新Activity.onCreate-onStart-Resume--旧Activity.onStop。)
  2. 在ActivityThread中完成activity、application的创建和绑定,并调用界面显示等;

具体流程如下:

  1. Activity的startActivity
  2. Instrumentation#execStartActivity
    1. ActivityManagerNative.getDefault().startActivity;(getDefault()返回的是ActivityManagerService的远程接口ActivityManagerProxy,通过binder通信调用ActivityManagerService.startActivity。AMS通知ActivityThread是通过ApplicationThread(在frameworks/base/core/java/android/app/ActivityThread.java中)和ApplicationThreadProxy。)
    2. ActivityStarter.startActivityMayWait 中调用startActivityLocked;
      1. 解析Intent得到更多信息
      2. 调用startActivityLocked;
      3. startActivity方法;
      4. startActivityUnchecked;
    3. ActivityStarter.startActivityUnchecked(实质会根据信息中launchMode,flag等来计算调度ActivityStack中的task,ActivityRecord等,);
      1. ActivityStack.startActivityLocked(源码为mTargetStack.startActivityLocked。将activity添加到栈顶,初始化WindowManager,回到StackSupervisor,调用StackSupervisor.resumeTopActivitiesLocked,再调回ActivityStack.resumeTopActivityInnerLocked);
        1. WindowManagerService.prepareAppTransition 去准备activity跳转动画
        2. next.setVisibility 去使得动画可见
      2. 调用ActivityStack.startPausingLocked暂停交互当前Activity,里面通过prev.app.thread.schedulePauseActivity调用ActivityThread.handlePauseActivity,接着调用performPauseActivityIfNeeded,然后是Instrumentation 的callActivityOnPause,调用activity.performPause();然后的onPause,然后调用ActivityManagerNative.getDefault()(获取代理对象ActivityManagerProxy).activityPaused告诉ActivityManagerService 旧的Activity已经onPause,可以启动新的Activity了。
    4. ActivityStackSupervisor.startSpecificActivityLocked:(如果是新进程就调用startProcessLocked;如果不是就调用realStartActivityLocked)
      1. 在新进程中启动时会执行到startProcessLocked(最终调用ActivityManagerService.startProcessLocked去创建新进程,主要是调用Process.start接口来创建一个新的进程,新的进程会导入android.app.ActivityThread类,并且执行它的main函数)
      2. ActivityThread.main调用attach方法,最终调到ActivityManagerService.attachApplicationLocked里面,此时Process(并不是application)已经创建,就调用ActivityStackSupervisor.realStartActivityLocked(里面也有更新Configuration去真正启动activity,最终调用到ActivityThread.handleLaunchActivity:
  3. ActivityThread.handleLaunchActivity;
    1. handleLaunchActivity:
      1. 解析前面传过来的ActivityClientRecord,来收集activity的相关信息(是前面生成的);
      2. performLaunchActivity去实例化activity对象和application对象;
        1. 用mInstrumentation.newActivity去实例activity
        2. 调用LoadedApk.makeApplication:去创建application对象(若使用了多进程,application对象会存在多个。);
        3. 创建Configuration;
        4. 调用activity.attach把activity、application和window关联起来(需要用到Configuration)
        5. 设置应用theme主题;
        6. 通过调用mInstrumentation.callActivityOnCreate去调用Activity.performCreate,里面可以调用onCreate;
        7. 调用mInstrumentation.callActivityOnRestoreInstanceState
      3. handleResumeActivity:
        1. performResumeActivity;
          1. Activity.performResume:
            1. performRestart:
            2. onResume:
        2. decor.setVisibility(View.INVISIBLE);此时视图才可见。

切换Activity窗口时Window变化的过程可参考:

Android窗口管理服务WindowManagerService切换Activity窗口(App Transition)的过程分析_罗升阳的博客-CSDN博客


进程启动流程

ActivityManagerService.startProcessLocked--ProcessList.startProcessLock---Process.start---ZygoteProcess.start-----startViaZygote---zygoteSendArgsAndGetResult(参数openZygoteSocketIfNeeded中打开socket和zygote通信)---attemptZygoteSendArgsAndGetResult

Android应用启动过程

相关类简介

(参考:android 从点击图标到启动Activity的流程_ambitionsd的博客-CSDN博客):

ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期

ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作

ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。

ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。

Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。

ActivityStack:这个并不是我们平时所说的任务栈,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。ActivityStack管理了一系列的TaskRecord,通过mStackId来唯一标识,持有ActivityStackSupervisor的引用。

ActivityStackSupervisor,这是高版本才有的类,它用来管理多个ActivityStack,早期的版本只有一个ActivityStack对应着手机屏幕,后来高版本支持多屏以后,就
有了多个ActivityStack,于是就引入了ActivityStackSupervisor用来管理多个ActivityStack。

ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。

TaskRecord:这个才是我们平时所说的任务栈,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。

ActivityStarter:启动activity相关逻辑;

App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。

另外强烈推荐看下:https://www.jianshu.com/p/94816e52cd77

这篇文章详细介绍了ActivityRecord、 TaskRecord,ActivityStack。

启动权限问题

在ActivityStarter.startActivity中有如下几处权限判断地方:

展锐平台:

  if(!am.judgeStartAllowLocked(intent, targetPkg, targetUid, callingUid, callingPackage, "start-activity")){
            return ActivityManager.START_INTENT_NOT_RESOLVED;
        }

ActivityManagerService.judgeStartAllowLocked---PowerControllerInternal.judgeAppLaunchAllowed----BackgroundCleanHelper.judgeAppLaunchAllowed

白名单在 Util.mWhiteAppList 和 BackgroundCleanHelper.mInternalWhiteAppList

Android原生:

        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
                inTask != null, callerApp, resultRecord, resultStack);
        if (abort) Slog.i(TAG,"->startActivity for " + intent
                + " checkStartAnyActivityPermission result:false");
        boolean firewallCheck = !mService.getPermissionPolicyInternal().checkStartActivity(intent,
                        callingUid, callingPackage);
        if (firewallCheck) Slog.i(TAG,"->startActivity for " + intent
                + " mIntentFirewall.checkStartActivity result:false");
        abort |= firewallCheck;

ActivityManager.checkComponentPermission---PackageManagerService.checkUidPermission----PermissionManagerService.checkUidPermission (通用权限校验)

PermissionPolicyService.Internal.checkStartActivity----isActionRemovedForCallingPackage(判断action在该SDK上是否被移除了)

判断权限是否需要review.

       // If permissions need a review before any of the app components can run, we
        // launch the review activity and pass a pending intent to start the activity
        // we are to launching now after the review is completed.
        if (aInfo != null) {
            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    aInfo.packageName, userId)) {
                IIntentSender target = mService.getIntentSenderLocked(
                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
                        callingUid, userId, null, null, 0, new Intent[]{intent},
                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
                                | PendingIntent.FLAG_ONE_SHOT, null);

                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值