前言
APP启动流程涉及的类和调用的方法还是蛮多的,做为android应用开发其实知道整个流程和重要的调用方法就够了。但是在了解整个流程前,得先知道涉及的相关知识,这样才能更好理解后面整个流程。后面源码分析基于Android-2.2_r1。
Zygote
zygote名字翻译叫受精卵,首先要知道zygote进程的创建是由Linux系统中init进程创建的,Android中所有的进程都是直接或者间接的由init进程fork出来的,Zygote进程负责其他进程的创建和启动,比如创建SystemServer进程。当需要启动一个新的android应用程序的时候,ActivityManagerService就会通过Socket通知Zygote进程为这个应用创建一个新的进程
Launcher
我们要知道手机的桌面也是一个App我们叫它launcher,每一个手机应用都是在Launcher上显示,而Launcher的加载是在手机启动的时候加载Zygote,然后Zygote启动SystenServer,SystenServer会启动各种ManageService, 包括ActivityManagerService,并将这些ManageService注册到ServiceManage 容器中,然后ActivityManagerService就会启动Home应用程序Launcher.
ActivityManagerService
ActivityManagerService我们简称AMS,首先当我们看到名字的时候,我们以为他是管理Activity的,其实四大组件都归它管,四大组件的跨进程通信都要和它合作,后面讲Binder时候会提到它。
AMS管理Activity主要是管理什么呢? 这就要说到AMS的相关类:
ProcessRecord 表示应用进程记录,每个应用进程都有对应的ProcessRecord对象
ActivityStack 该类主要管理回退栈
ActviityRecord 每次启动一个Activity会有一个对应的ActivityRecord对象,表示一个Activity的一个记录
ActivityInfo Activity信息,比如启动模式,taskAffinity,flag信息
TaskRecord Task记录信息,一个Task可能有多个ActivityRecord,但是一个ActivityRecord只能属于一个TaskRecord
Binder
Binder是Android跨进程通信(IPC)的一种方式,也是Android系统中最重要的特性之一,android 四大组件以及不同的App都运行在不同的进程,它则是各个进程的桥梁将不同的进程粘合在一起。
学习Binder首先要知道相关客户端、服务端的概念,然后去把AIDL弄透彻, 知道系统生成的Aidl Java文件中每一个类所代表的是什么角色,然后看源码,能将ActivityManageService 用来跨进程同通信中各个角色弄明白就算是理解了,不过这只是一部分部分,得多总结归纳。
ActivityThread
首先ActivityThread并不是一个Thread,其作用就是在main方法内做消息循环。那我们常说的主线程是什么?主线程就是承载ActivityThread的Zygote fork而创建的进程 ,这里可能有人会不能理解进程和线程的区别,这里不详细讲述自行学习。ActivityThread的调用是在ActivityManageService.startProcessLocked()方法里调用并创建,这个类主要做了这几个事
创建Looper,开启Looper循环
创建内部类 H,H继承于Handler 用于跨进程通信切换线程
创建ApplicationThread跨进程Binder对象mAppThread。 这里要说一点,ActivityThread通过ApplicationThread与AMS进行通信,ApplicationThread通过H与ActivityThread进行通信(handler机制),处理Activity的事务
启动方式
app的启动我们将其分为两种:
冷启动:当应用启动的时候,后台没有当前应用的进程,这时系统会创建一个新的进程分配给应用。
热启动:当前应用已经打开,但是被按下返回键或者Home键退出到桌面或者去到其他App,当再次回到应用时就是热启动。
这里我们主要介绍冷启动过程,首先简单介绍下冷启动的的整个流程,然后再根据关键代码讲解。
App启动5步走
借用GITYUAN大神的一张图结合启动App逻辑讲一下App启动的整个流程,不过这是一张Launcher App启动的图,和我们要说的有点不一样,我们根据老罗所说的将App启动分为5步
Launcher通过Binder进程间通信机制通知ActivityManagerService,
它要启动一个Activity;
ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态, 于是ActivityManagerServicey利用Zygote.fork()创建一个新的进程,用来启动一个ActivityThread实例, 即将要启动的Activity就是在这个ActivityThread实例中运行;
ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,
以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
ActivityManagerService通过Binder进程间通信机制通知ActivityThread,
现在一切准备就绪,它可以真正执行Activity的启动操作了。
第一步1-3
Launcher的点击监听
首先我们在物理上点击了手机屏幕上的App快捷键图标,这里Launcher是这么操作的呢?我看位于android.launcher2下的源码Launcher
1、 这里可以看到,Launcher继承于Activity,并在其onClick()事件中监听了app的图标点击,调用了Launcher的startActivitySafely()方法
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {
...
/**
* Launches the intent referred by the clicked shortcut.
*
* @param v The view representing the clicked shortcut.
*/
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
startActivitySafely(intent, tag);
} else if (tag instanceof FolderInfo) {
handleFolderClick((FolderInfo) tag);
} else if (v == mHandleView) {
if (isAllAppsVisible()) {
closeAllApps(true);
} else {
showAllApps(true);
}
}
}
...
}
2、这里将这个启动方式使用Intent.FLAG_ACTIVITY_NEW_TASK, 创建了一个新的TASK栈,然后继续调用父类Activity
的startActivity()
方法
void startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
} catch (SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Launcher does not have the permission to launch " + intent +
". Make sure to create a MAIN intent-filter for the corresponding activity " +
"or use the exported attribute for this activity. "
+ "tag="+ tag + " intent=" + intent, e);
}
}
3、Activity的startActivity()方法中传递了默认为-1的requestCode,表示不需要返回值,然后调用了startActivityForResult(),在这个方法中我们看到一个mInstrumentation变量,这个变量是Instrumentation对象的实例,具体是在Activity的attach()方法中进行赋值的。然后startActivityForResult()方法中调用了mInstrumentation.execStartActivity()方法,然后在其中传递了两个参数我们要介绍下,
mMainThread.getApplicationThread():mMainThread变量声明是 ActivityThread对象,而getApplicationThread()方法则返回的是ApplicationThread的实例。
mToken :的声明为 private IBinder mToken;
这里为什么传递这两个参数我们后面说,我们继续看execStartActivity()方法。
@Override
public void startActivity(Intent intent) {
startActivityForResult(intent, -1);
}
public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
第二步4-7
4、我们继续看位于android/app/Instrumentation.java中的execStartActivity方法,最后调用了ActivityManagerNative.getDefault().startActivity()方法,就要和AMS进行Binder的ICP通信了,AMS会收到startActivity的请求,执行startActivity()方法。
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i = 0; i < N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
int result = ActivityManagerNative.getDefault().startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), null, 0, token,
target != null ? target.mEmbeddedID : null, requestCode, false, false);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
5、首先我们知道Launcher本来就是一个Activity,并单独处于一个进程中,现在要启动另一个我们所点击的APP的Activity,而AMS是管理所有Activity的,那么我们就会和AMS使用Binder进行跨进程通信。
这里我们也具体了解下是谁和AMS进行跨进程通信?
使用Binder进行通信,就首先得有Server进程和Client进程,
首先Server会提供一套接口函数供Client调用,这个时候通常会采用Proxy设计模式。将接口定义在一个抽象类中,Server和Client都会以该抽象类为基础实现所有函数。 而在Client端会具有Server端的代理对象Proxy,Proxy具有和Server一样的方法,Client使用代理对象经过Binder的转换,跨进程调用Server的服务。具体理解这一块先看看AIDl相关。
再回到步骤4 的ActivityManagerNative.getDefault().startActivity()方法,这个方法后面调用asInterface()然后返回ActivityManagerProxy对象,这个对象其实就是AMS在客户端的代理对象,ActivityManagerProxy实现IActivityManager接口,具有AMS所提供的方法,不同的是,ActivityManagerProxy并没有实现方法,ActivityManagerProxy只是将客服端发起的请求进行参数进行打包封装,并在每一个方法中添加唯一表示,然后将请求发送到Binder,Binder就会将请求转发给server,server根据唯一表示调用相应的server的相关方法。
再看下AMS:AMS继承了ActivityManagerNative同样实现了IActivityManager接口。这里就能
也就是说与AMS通信的其实是AMS的代理对象ActivityManagerProxy,通过:ActivityManagerProxy -> Binder驱动 -> AMS
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
class ActivityManagerProxy implements IActivityManager{}
private final class ApplicationThread extends ApplicationThreadNative {}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
。。。
static public IActivityManager getDefault()
{
...
IBinder b = ServiceManager.getService("activity");
if (Config.LOGV) Log.v(
"ActivityManager", "default service binder = " + b);
gDefault = asInterface(b);
...
return gDefault;
}
static public IActivityManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
class ActivityManagerProxy implements IActivityManager{}
...
}
6、Activity通过Binder将消息传递到了AMS,AMS的startActivity()方法接收到方法开始一系列的调用,这里整个AMS会做几个操作
对参数intent的内容进行解析,保存到ResolveInfo对象中
从传进来的参数得到调用者的进程信息,保存到ProcessRcord对象中,这里获取的就是Launcher应用程序的进程
创建即将要启动的Activity的相关信息 保存到ActivityRecord对象
根据intent的参数设置启动模式,并创建一个新的Task来启动这个Activity
将创建的Task保存到ActivityManagerService
将Launcher推入Paused状态