简介:
在android系统中,Home界面也就是Launcher的界面,Launcher它本身也是一个应用程序,在其它程序安装完成以后,会在Launcher中出现一个图标,点击该图标,对应该图标的应用程序也就会启动起来。
在说明整个启动流程之前,我们首先需要了解几个用到的主要类:
1. Launcher类
Launcher俗称HomeScreen,也就是我们启动Android手机,第一眼看到的就是这个应用程序,而这个应用程序是比较特殊而且任务艰巨的。它负责了我们除了应用本身操作以外的所有操作,它负责了我们有几个桌面,点击应用图标启动应用程序,长时间按桌面出现上下文菜单,长时间按桌面的图标出现垃圾箱,拖动应用图标重新定位等等,一系列的操作。
2. Intrumentation类
官方的解释为:
/** Base class for implementing application instrumentation code. When running
* with instrumentation turned on, this class will be instantiated for you
* before any of the application code, allowing you to monitor all of the
* interaction the system has with the application. An Instrumentation
* implementation is described to the system through an AndroidManifest.xml's
* <instrumentation> tag.*/
大意为:Instrumentation类会在应用的任何代码执行前被实列化,用来监控系统与应用的交互。
在本文介绍的启动流程当中,Instrumentation则搭建起了从Launcher到ActivityManagerNative桥梁,从ActivityManagerNative作为起始点,开启了整个App启动的流程。
3. ActivityManagerNative类
ActivityManager的功能是与系统中所有运行着的Activity交互提供了接口,主要的接口围绕着运行中的进程信息,任务信息,服务信息等。而在后续的介绍中,会谈到ActivityManager到ActivityManagerService之间的交互,它们二者交互中会经过一个环节,那就是进程通信,而IActivityManager以及实现接口的代理类ActivityManagerProxy,存根类ActivityManagerNative起着负责进程通信的作用,虽然这里没有使用aidl文件定义进程通信接口IActivityManager,其实是一样的,我们可以把它看做是自己手动编译的aidl进程通信java类实现,ActivityManagerProxy是代理类,ActivityManagerNative是Stub类,IActivityManager是aidl接口。
4. ActivityStack类
正如其名,ActivityStack是一个用于管理Activity栈结构的类,下面有对栈结构的简单介绍:
Activity承担了大量的显示和交互工作,从某种角度上将,我们看见的应用程序就是许多个Activity的组合。为了让这许多 Activity协同工作而不至于产生混乱,Android平台设计了一种堆栈机制用于管理Activity,其遵循先进后出的原则,系统总是显示位于栈 顶的Activity,从逻辑上将,位于栈顶的Activity也就是最后打开的Activity,这也是符合逻辑的。
在操作应用程序时,每次启动新的Activity,都会将此压入Activity Stack,当用户执行返回操作时,移除Activity Stack顶上的Activity,这样就实现了返回上一个Activty的功能。直到用户一直返回到Home Screen,这时候可以理解为移除了Activity Stack所有的Activity,这个Activity Stack不再存在,应用程序也结束了运行。
5. ActivityThread类
它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行activities、broadcasts和其它操作。
6. ActivityApplication类
该类在其它博客和论坛上有很详细的说明,这里我们引入一些比较简单明了的解释:
Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建,如果需要创建自己 的Application,也很简单创建一个类继承 Application并在manifest的application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。
android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作。
7. ActivityManagerService类
ActivityManagerService是非常值得深入学习的,这里只笼统的说明一下他的功能:
ActivityManagerService是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要。
额外补充:
除上面提到的信息以外,还需要对Android系统进程间通讯Binder机制有一定的了解,由于本文中只介绍app的启动流程,对于Binder机制,这里就从网上找了一些基本嘻嘻,进行简单说明一下:
Android系统存了Zygote进程和SystemServer进程以及各种应用进程等,为了能够实现各种进程之间的通讯,Android系统采用了自己的进程间通讯方式Binder机制。其中主要涉及到了四种角色:Binder Client,Binder Server,Binder Manager, Binder driver。各种角色之间的关系可以参考下面这张图的介绍:
流程及源码:
下面我们详细介绍一下点击后,整个源码的运行流程:
1.Launcher:
1.a 位于packages/apps/Launcher2目录。
1.b 源码部分:
在点击了Launcher界面中的App的图标以后,会执行其中的onClick方法,其中intent为我们在AndroidManifest.xml文件中配置的信息:
同时,从代码中可以发现其中最终调用了startActivitySafely方法:
可以发现内部则又调用了startActivity方法,但是我们在Launcher类中没有发现有该方法,由 于Launcher类为Activity类的子类,我们可以在其父类中进行查找,发现其中有我们正在查找的方法:
它本身由调用了startActivityForResult进行处理,其中传入的参数-1代表结束后,不需要这个Activity的结果,让我们再来看这个startActivityForResult:
可以发现,在startActivityForResult方法内部,又调用了Intrumentation类的对象中的execStartActivity方法,执行时,传入了相应的参数,其中:
A. mMainThread:为Activity成员变量,类型Activity Thread,它代表的是应用程序的主线程。
B. mMainThread.getApplicationThread():则是为了获取其内部的Application Thread内部类,在随后的流程中,它作为一个Binder对象,扮演了一个链接通讯的角色,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。
C. mToken:为一个Binder对象的远程接口。
2. Instrumentation.execStartActivity
2.a 作用:
它用来监控应用程序和系统的交互。
2.b 位置:
package android.app(1492行)
2.c 源码:
由于在上面中调用到了Instrumentation中的execStartActivity方法,我们直接来看该方法内部的源码:
在方法中可以看到,与startActivity相关的方法是:ActivityManagerNative.getDefault.startActivity方法,其中:
ActivityManagerNative.getDefault返回是ActivityManagerService的远程接口,即为ActivityManagerProxy的接口,通过该接口调用startActivity方法,在参数中可以发现,传入了intent.resolveTypeIfNeeded这个参数,实则为AndroidMainfest.xml中的设置的MIME类型,从上面配置的信息中,我们可以知道intent并没有配置MIME类型,因此在此返回null,不用做考虑。
3. ActivityManagerProxy.startActivity
3.a 作用:
提供IActivityManager,根据参数,执行接口中提供的对应方法。
3.b 位置:
ActivityManagerNative中的内部类(3044行)
3.c 源码:
在ActivityManagerProxy的startActivity方法中,可以看见对传入的参数及信息封装到一个Parcel类型的Data包内,在封装完成后,执行了IBinder类型mRemote变量中的transact方法,其中传入的对应startActivity行为的参数START_ACTIVITY_TRANSACTION。
4. ActivityManagerService.startActivity
4.a 作用:
在经过上面的mRemote变量的transact方法执行以后,最终会通过Binder机制,进入到ActivityManagerService当中,执行startActivity方法。
4.b 位置:
android.server.am目录下
4.c 源码:
位置(4282行)
执行的内容:
最终是将操作交给了mActivityStarter中的startActivityMayWait去执行。
5. ActivityStarter.startActivityMayWait
5.a 作用:
对intent中传来的信息进行封装,同时调用startActivityLocked进行下一步操作。
5.b 位置:
android.server.am目录下
5.c 源码:
位置:(675行)
在startActivityMayWait方法中,与启动相关的内容主要有:
这部分内容,除了在新的intent中封装好即将启动的应用程序信息内容以外,同时,调用resolveIntent方法,负责将intent中的内容给解析出来,得到MainActivity的相关信息,保存在ainfo变量当中。
在最后的时候,调用startActivityLocked(819行)方法去进一步处理。
6. ActivityStarter.startActivityLocked
6.a 作用:
接收并保存调用者的进程信息,并调用startActivityUncheckedLocked去进行下一步操作
6.b 位置:
android.server.am目录下
6.c 源码:
位置:(224行)
startActivityLocked方法中内部会将调用该方法的进程对象,即caller的进程信息(Launch),保存在callerApp当中,用于下面的ActivityRecord记录用。
同时,作为Launcher这个Activity里面的一个Binder对象,它可以获得LauncherActivity的相关信息,同时也被该方法的sourceRecord变量记录了下来。
随后,所有即将用到的进程信息会被传入创建的ActivityRecord类型对象r(493行)当中。
最后调用startActivityUnchecked(535行)方法将r对象,sourceRecord等参数传入该方法中。
7 ActivityStack.startActivityUnchecked等方法
7.a 作用:
判断即将启动的Activity是否需要在新的task中进行创建和创建新的Task
7.b 位置:(959行)
在执行时,会调用getReusableIntentActivity方法去看当前有没有Task可以用来执行这个Activity。
在该方法中,由于没有在AndroidMainfest.xml中设置launchmode,因此默认情况下为0,即standard的情况。因此在检查时候,会执行对应条件中的findTaskLocked方法,由于这个Activity当前都没有创建过,因此,必然返回为null值。
因此,会调用上面的setTaskFromReuseOrCreateNewTask(1091行)方法,进行Task的创建。该方法中会将新建Task,并将新建的Task添加进TaskRecord当中做记录。
最后会调用ActivityStack类型的变量mTargetStack的startActivityLocked来进行进一步处理。
8 ActivityStack.startActivityLocked
8.a作用:
确保当前要开启的activity添加到新建的task的顶端。
8.b位置:(2636行)
8.c源码:
调用了addActivityToTop确保即将开启的Activity被添加到Task的顶部。随后调用resumeTopActivityInnerLocked(2113行)方法。
9 ActivityStack.resumeTopActivityInnerLocked
9.a 作用:
将位于当前正在运行的LaunchActivity由Resumed状态转换为Paused状态
9.b 位置:(2113行)
9.c 源码:
将栈顶的Activity取出来,这里的栈顶的Activity,就是刚刚添加到栈顶MainActivity,这时候取出来保存到next变量中。
与当前Activity相关的,则还包括上面的判断,mLastPausedActivity会将栈顶Activity转换为休眠状态时赋值给自己,而我们当前的LaunchActivity由于仍处于Resumed状态,因此跳过本判断,继续往下进行。
这时,由于当前正在处于Resumed状态下的Activity是LaunchActivity,则此时,就会走该判断逻辑中的startPausingLocked(2252行)方法,将LaunchActivity推送到Paused状态。
10 ActivityStack.startPausingLocked
10.a 作用
将当前处于Resumed状态的Activity转换为Paused状态
10.b 位置:(1076行)
10.c 源码:
当前的LaunchActivity会作为参数赋值给prev变量。
在随后的逻辑判断中,由于LaunchActivity是在Zygote创建的时候,其app及thread就被创建完成了,因此必然不为null,prev.app.thread为通过它来通知Launcher这个Activity它要进入Paused状态了。当然,这里的prev.app.thread是一个ApplicationThread对象的远程接口,通过调用这个远程接口的schedulePauseActivity来通知Launcher进入Paused状态。
这时就会调用ApplicationThreadProxy,该代理类中的schedulePauseActivity方法。
11 ApplicationThreadProxy.schedulePauseActivity
11.a 作用:
通过Binder进程间通信的机制,进入到ApplicationThread.schedulePauseActivity(657)方法当中。
11.b 位置:(775行)
11.c 源码:
该初就是将LaunchActivity的相关信息存入Parcel类型的data变量当中。最终通过Binder类型的mRemote对象运用进程间通讯的机制,调用ActivityThread.schedulePauseActivity。
12 ActivityThread.schedulePauseActivity
12.a 作用:
发送将LaunchActivity转换为Paused状态的信息。
12.b 位置:(657行)
12.c 源码:
这里finished参数代表的是传入的参数为prev对象所代表的Activity是否正在等待结束的Activity列表中,当前LaunchActivity当然不在这个队列中,还在Resumed的情况下呢。因此必然为PAUSE_ACTIVITY传参,这时就可以将信息发送出去了。
13 ActivityThread.handleMessage.handlePauseActivity
13.a 作用:
接收并处理发送来的信息请求
13.b 位置:(1469行)
13.c 源码:
根据msg传入的what信息,在handleMessage找到对应的PAUSE_ACTIVITY项。
在handlePauseActivity方法中,主要做了以下三件事情:
A. A.1 传入的userLeaving值为在步骤7的方法源码中,判断intent标记是否有Intent.FLAG_ACTIVITY_NO_USER_ACTION,如果没有设置,则为true。我们在AndroidMainfest.xml文件中并没有配置。因此此处的userLeaving为true。
A.2 此时回调用performUserLeavingActivity函数来调用Activity.onUserLeaveHint通知Activity,用户要离开它了,进行相应操作。
B. 调用performPauseActivity函数来调用LaunchActivity中的OnPause方法。
C. 它通知ActivityManagerService,这个Activity已经进入Paused状态了ActivityManagerService现在可以完成未竟的事情,启动MainActivity。
14 ActivityManagerProxy.activityPaused
14.a 作用:
运行方法,利用Binder机制执行actiityPaused方法
14.b 位置:(3585行)
14.c 源码:
看到这段代码是不是很熟悉,是的,在此利用了代理类来执行了IBinder类型mRemote变量中的transact方法,不过这次传入的ACTIVITY_PAUSED_TRANSACTION字段,执行的是pause方法。这时会会到ActivityManagerService中执行activityPaused方法。
15 ActivityManagerService.activityPausedLocked
15.a 作用:
调用ActivityStack中的activityPausedLocked方法
15.b 位置:(6857行)
15.c 源码:
16 ActivityStack.activityPausedLocked
16.a 作用:
执行completePauseLocked方法
16.b 位置:(1189行)
16.c 源码:
当前一直在运行想要转入Pause状态的是LaunchActivity,传入的IBinder类型token值则对应的就是LaunchActivity,因此mPausingActivity与r均为LaunchActivity,则执行其中completePauseLocked方法。
17 ActivityStack.completePauseLocked
17.a 作用:
调用ActivityStackSupervisor中的开启Activity方法
17.b 位置:(1270行)
17.c 源码:
它主要负责了两件事情,一件是将原来为LaunchActivity的mPausingActivity滞空。(1311)
另外一件事情就是调用resumeFocusedStackTopActivityLocked(1317行)方法,获得当前堆栈顶端的Activity,如我们之前的步骤所记,我们新建了一个task,并将即将启动的MainActivity添加到栈顶,则当前的Activity就是我们即将要启动的MainActivity,此时通过该方法,将其取出来并存储与next当中,然后最终调用其中的ActivityStackSupervisor中的startSpecificActivityLocked()方法,将next传入,开启next所代表的MainActivity(2514行)。
18 ActivityStack.Supervisor.startSpecificActivityLocked
18.a 作用:
判断是否开启该进程,如果没有则调用ActivityManagerService进行开启。
18.b 位置:(1355行)
18.c 源码:
在进入方法后会受限判断该应用是否已经开启,由于我们只是刚刚点开该程序,则取回来的app则肯定为空。
随后就会调用ActivityManagerService.startProcessLocked方法进行下一步操作。
19 ActivityManagerService.startProcessLocked
19.a 作用:
调用Process.start接口来新建一个新的进程
19.b 位置:(3477行-3487行-3600行-3616行-3743行)
19.c 源码:
经过几个方法到跳转,最终调用到了Process.start的方法,在调用Process.start方法之前,将一个字符串entryPoint作为参数传入到start方法中,通过该方法,我们创建一个新的进程,这里涉及到了Zygote中的Socket接口监听并调用孵化APP进程的过程,这里我们详细说明一下:
19.c.A 调用Process.start方法
19.c.B 内部调用了startViaZygote方法,我们再到该方法中看一下:
19.c.C 可以发现在其最后,又调用了zygoteSendArgsAndGetResult方法:
19.c.D 在zygoteSendArgsAndGetResult方法中,可以看到它调用了zygoteState对象(Zygote孵化完成后,开启到监听Socket),并借该对象通过Socket通信机制,让Zygote进程fork除了一个新的进程,并根据startProcessLocked方法中传递来的entryPoint(”android.app.ActivityThread”)字符串,反射出该对象并执行ActivityThread的main方法。此时我们可以进入ActivityThread的main函数中看下进行了哪些操作。
20 ActivityThread.main
20.a 作用:
创建消息循环及接收处理机制,并最终调用ActivityManagerService中的attachApplication。
20.b 位置:
20.c 源码:
进程在创建完成以后,调用了ActivityThread中的main函数,其中调用了attach函数,随后调用Looper的消息循环机制进行消息循环。
在attach方法中(5888行),通过ActivityMangerNative.getDefault方法获得到了ActivityManager的代理类ActivityManagerProxy,调用其中的attachApplication(3544行)函数。
该方法中又发现了我们熟悉的Binder类型对象mRemote,再次通过Binder机制,根据传入的ATTACH_APPLICATION_TRANSACTION字段,调用ActivityManagerService中的attachApplication方法(534行)。
21 ActivityManagerService.attachApplication
21.a 作用:
方法调用ActivityStackSupervisor类中的attachApplicationLocked方法。
21.b 位置:(6610行)
21.c 源码:
内部操作转发给了attachApplicationLocked方法(6384行)。
最终会调用位于6550行的ActivityStackSupervisor类中的attachApplicationLocked方法。
22 ActivityStackSupervisor.attachApplicationLocked
22.a 作用:
将此时将启动的MainActivity传递给realStartActivityLocked进行正式启动。
22.b 位置:(825行)
22.c 源码:
在该方法中,可以发现其通过调用topRunningActivityLocked将此时位于栈顶的MainActivity 取出来,存储于ActivityRecord类型的hr变量中,并将hr传递给realStartActivityLocked方法进行开启。
通过realStartActivityLocked方法,最终通过app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity函数中(709行),注意,这里的第二个参数r,是一个ActivityRecord类型的Binder对象,用来作来这个Activity的token值。此时我们进入到ActivityThreadProxy类中进行查看。
此方法就是将即将启动的Activity信息进行封装,并以LAUNCH_ACTIVITY的形式发送出去。最终交给ActivityThread中的HandleMessage进行处理。
然后再次移交给handleLaunchActivity进行处理。
23 ActivityThread.HandleMessage
23.a 作用:
23.b 位置:(2687行)
23.c 源码:
方法里主要执行了两个步骤:
第一个步骤执行了performLaunchActivity方法,该方法加载了这个Activity类,即MainActivity,然后调用它的onCreate函数,
第二步在回到handleLaunchActivity函数时,再调用handleResumeActivity函数来使这个Activity进入Resumed状态,即会调用这个Activity的onResume函数,这是遵循Activity的生命周期的。
我们这里主要研究一下performLaunchActivity方法。
24 ActivityThread.performLaunchActivity
24.a 作用:
保存组件信息,加载需要启动的Activity类,创建Application对象,并调用执行onCreate方法
24.b 位置:(2687行)
24.c 源码:
这段代码主要负责了收集启动的Activity的package和component信息。
这段代码主要负责将启动的Activity的类加载到内存当中
根据AndroidMainfest.xml中配置的Application信息,创建Application对象。
根据记录到ActivityRecord中的信息,设置Activity中的配置信息,以及上下文信息等
最后通过mInstrumentation的callActivityOnCreate函数来间接调用,前面我们说过,mInstrumentation在这里的作用是监控Activity与系统的交互操作,相当于是系统运行日志。
到这里,从点击app到启动app执行onCreate方法到一整个流程就进行完毕了。