IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

启动Activity的流程(Launcher中点击图标启动)

Android相关技术 2016-04-02 13:42:06 累计浏览 4,848 次
本机暂存

启动Activity一般有多种方式,常见的有三种:

  1. 在Launcher桌面点击app图标

  2. 调用startActivity启动一个Activity

  3. 命令am start启动

这三种方式在服务端的处理方式基本相同,客户端的请求方式也差别不大,理解其中之一就可以类推到其他方式。本文结合案例分析在Launcher桌面点击app图标启动应用的方式,再简要给出其他两种方式的区别。

案例

应用名称为TestLaunchApp,包含A和B两个Activity,A为入口类,点击按钮跳转到B

packagecom.example.startapptest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

publicclassAextendsActivity{
privatefinalstaticStringTAG="StartAppTest";

@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.i(TAG,"A"+"--------------onCreate()");
setContentView(R.layout.a_layout);
}

@Override
protectedvoidonResume(){
// TODO Auto-generated method stub
Log.i(TAG,"A"+"--------------onResume()");
super.onResume();
}

@Override
protectedvoidonPause(){
// TODO Auto-generated method stub
Log.i(TAG,"A"+"--------------onPause()");
super.onPause();
}

publicvoidfuncA(View view){
startActivity(newIntent("com.feeyan.www.b_activity"));
}

@Override
publicvoidonBackPressed(){
// TODO Auto-generated method stub
finish();
super.onBackPressed();
}
}
packagecom.example.startapptest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

publicclassBextendsActivity{
privatefinalstaticStringTAG="StartAppTest";

@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.i(TAG,"B"+"--------------onCreate()");
setContentView(R.layout.b_layout);
}

@Override
protectedvoidonResume(){
Log.i(TAG,"B"+"--------------onResume()");
super.onResume();
}

@Override
protectedvoidonPause(){
// TODO Auto-generated method stub
Log.i(TAG,"B"+"--------------onPause()");
super.onPause();
}

publicvoidfuncB(View view){
startActivity(newIntent("com.feeyan.www.a_activity"));
finish();
}
}
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">
    
    <Button
        android:id="@+id/button_a_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="50dp"
        android:onClick="funcA"
        android:text="@string/button_a_text"
        android:textSize="20sp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="154dp"
        android:text="@string/page_a_text"
        android:textSize="30sp"/>

</RelativeLayout>
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <Button
        android:id="@+id/button_b_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="50dp"
        android:onClick="funcB"
        android:text="@string/button_b_text"
        android:textSize="20sp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button_b_id"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="140dp"
        android:text="@string/page_b_text"
        android:textSize="30sp"/>

</RelativeLayout>
<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.startapptest"
    android:versionCode="1"
    android:versionName="1.0">

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="21"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".A"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.feeyan.www.a_activity">
                </action>

                <category android:name="android.intent.category.DEFAULT">
                </category>
            </intent-filter>
        </activity>
        <activity
            android:name=".B"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="com.feeyan.www.b_activity">
                </action>

                <category android:name="android.intent.category.DEFAULT">
                </category>
            </intent-filter>
        </activity>
    </application>

</manifest>

当点击A中的按钮时,跳转到B,先暂停A,A从前台转入到后台,开始执行B的onCreate、onResume方法,B被调入到栈顶,B现在可见,日志为:

I/StartAppTest(26256):A--------------onCreate()
I/StartAppTest(26256):A--------------onResume()
I/StartAppTest(26256):A--------------onPause()
I/StartAppTest(26256):B--------------onCreate()
I/StartAppTest(26256):B--------------onResume()

启动一个Activity的标志是开始执行生命周期onCreate方法,转入到后台的标志是onPause方法,正在运行、可见的标志是onResume方法,本文将从源码着手,分析启动activity的过程。

1. 在Launcher桌面点击app图标启动入口Activity

本文基于android5.1.1源码,在Launcher主页面当点击图表时,调用过程为:

onClick—->……—->startActivitySafely—->startActivity(v, intent, tag)—->startActivity(intent, optsBundle);

源码:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

intent设置了FLAG_ACTIVITY_NEW_TASK标志,表示开启一个新任务,在新任务中启动activity,本案例没有特殊的动画设置,optsBundle为null。

framework层客户端

过程1    frameworks\base\core\java\android\app\Activity.java

startActivity所属的对象是this,表示当前启动类Launcher对象,下一步执行到Activity的startActivity方法,过程为:

startActivity(Intent intent, @Nullable Bundle options)

—-> startActivityForResult(intent, -1)

—-> startActivityForResult(intent, requestCode, null)

注:由于源码较长,本文不贴上全部源码,只给出方法名称、部分代码以及源码路径

action为字符串“com.feeyan.www.b_activity”,requestCode等于-1,如果>=0, B被启动后会返回到A中,且A中的onActivityResult()方法会被调用。即便是调用startActivity,还是会调到 startActivityForResult,只不过此时requestCode是-1了。

mParent:如果不为空,表示当前Activity有子类,本案例没有子类,为空,进程执行到:

Instrumentation.ActivityResult ar=
                mInstrumentation.execStartActivity(
                    this,mMainThread.getApplicationThread(),mToken,this,
                    intent,requestCode,options);

要搞懂源码,最关键的就是弄清楚参数的具体含义,源码中参数有时候多达十几个,如果不清楚参数的来龙去脉,无从分析。

this:当前进程还是在Launcher所在的进程,this就是Launcher类的一个对象。

mMainThread.getApplicationThread():返回一个ApplicationThread对象类型,也是一个IBinder对象类型,,mMainThread是ActivityThread的一个对象,代表当前Launcher主线程对象

mToken:也是一个IBinder对象类型

requestCode仍为-1,options为null

过程2    frameworks\base\core\java\android\app\Instrumentation.java

publicActivityResult execStartActivity(
            Context who,IBinder contextThread,IBinder token,Activity target,
            Intent intent,intrequestCode,Bundle options){
            ......
}

this对象传给execStartActivity,该函数的第一个形参who是Context类型,第4个形参target是Activity类型,其实际类型都是Launcher对象,只是名字起的不一样,这就是一种共识,代表着某种含义,读者看到名字就能猜得着其用意。

IApplicationThread whoThread=(IApplicationThread)contextThread;

contextThread既是IBinder对象,也是IApplicationThread对象,此处向上转型为IApplicationThread对象,

intresult=ActivityManagerNative.getDefault()
                .startActivity(whoThread,who.getBasePackageName(),intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token,target!=null?target.mEmbeddedID:null,
                        requestCode,0,null,options);

ActivityManagerNative实现了IActivityManager接口,调用getDefault方法最终返回ActivityManagerService的代理类ActivityManagerProxy的一个对象,于是,startActivity便转入到ActivityManagerProxy对象中开始执行。

过程3    frameworks\base\core\java\android\app\ActivityManagerNative.java

publicintstartActivity(IApplicationThread caller,StringcallingPackage,Intent intent,
            StringresolvedType,IBinder resultTo,StringresultWho,intrequestCode,
            intstartFlags,ProfilerInfo profilerInfo,Bundle options)throwsRemoteException{
......
}

分析参数时,结合实际参数来看,否则单独看形参不能确定具体含义。

caller:前面传过来的值,代表ApplicationThread对象

callingPackage:由who.getBasePackageName()的值传递而来,who是Context对象,getBasePackageName()的实现在ContextImple中,返回当前启动类的包名,就是Launcher的包名

resolvedType:解析当前发送的Intent的MIME数据类型,本案例没有为intent设置type、data属性,因此,intent.resolveTypeIfNeeded(who.getContentResolver())返回null

resultTo:Ibinder对象,具体含义后面继续看

resultWho:由target != null ? target.mEmbeddedID : null得来,target是activity对象即启动类Launcher对象,不为空,该语句返回mEmbeddedID,一个id号,这个值必须要从Launcher这个apk启动中获得,在Launcher启动后,代表Launcher启动类的对象是一个ActivityClientRecord对象,该对象所属的类路径为:

frameworks\base\core\java\android\app\ActivityThread.java

该对象的scheduleLaunchActivity方法中,有一句:

ActivityClientRecord r = new ActivityClientRecord();

在ActivityClientRecord的构造方法中会把embeddedID初始化为null,因此mEmbeddedID为空

startFlags:整型值,已经初始化为0,具体作用后面分析

profilerInfo:为null,具体作用后面分析

这些参数都会被打包到持久化类Parcel的对象data中,把data作为transact的参数进行跨进程传递:

mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

该方法通过binder通信机制会传递到ActivityManagerNative的onTransact方法,在onTransact方法中,根据发送命令START_ACTIVITY_TRANSACTION找到case处理语句,把data中的数据取出来赋给相应的变量,继续调用:

intresult=startActivity(app,callingPackage,intent,resolvedType,
                    resultTo,resultWho,requestCode,startFlags,profilerInfo,options);

startActivity最终会调用到服务端ActivityManagerService中。此时,进程也从启动类Launcher所在的进程切换到了服务端进程。从ActivityManagerNative.getDefault().startActivity一直到ActivityManagerService的startActivity方法,主要由binder通信实现,该过程相当复杂,但binder通信不属于本文重点,而且binder机制贯穿于整个Android系统、内核、驱动部分,本文如再遇到binder通信机制,直接给出最终被调用的类及方法。

在进入到服务端之前,看看客户端到底做了哪些工作?

主要是获得了一些必要的参数:IApplicationThread对象、启动类包名、Intent的MIME数据类型、IApplicationToken.Stub类型对象resultTo等,除了这些,没有其他特殊的操作了,其实最关键的操作还是在服务端进行的,这就是为何本文一开始提到无论哪种启动方式,客户端都是大同小异。

framework层服务端

过程4    frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

startActivity—->startActivityAsUser—->mStackSupervisor.startActivityMayWait

mStackSupervisor.startActivityMayWait(caller,-1,callingPackage,intent,
                resolvedType,null,null,resultTo,resultWho,requestCode,startFlags,
                profilerInfo,null,null,options,userId,null,null);

这几步没有太多的操作,获得了一个用户id,用来作一些检测

过程5    frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

finalintstartActivityMayWait(IApplicationThread caller,intcallingUid,
            StringcallingPackage,Intent intent,StringresolvedType,
            IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,
            IBinder resultTo,StringresultWho,intrequestCode,intstartFlags,
            ProfilerInfo profilerInfo,WaitResult outResult,Configuration config,
            Bundle options,intuserId,IActivityContainer iContainer,TaskRecord inTask){
    ......
}

先看多了哪些参数:
voiceSession:IVoiceInteractionSession对象类型,被初始化null。IVoiceInteractionSession本是一个aidl远程接口,定义了任务栈启动taskStarted、任务栈结束taskFinished等方法

voiceInteractor:IVoiceInteractor对象类型,被初始化为null。IVoiceInteractor也是一个aidl远程接口

outResult:WaitResult对象类型,被初始化为null。WaitResult是IActivityManager的内部类,实现了Parcelable接口,主要用来保存启动Activity后返回的结果信息

config:Configuration对象类型,被初始化为null。Configuration描述了所有设备相关的配置信息,比如,本地语言、屏幕大小、屏幕方向、输入法模式,可以通过Resources的getConfiguration获得改对象

iContainer:IActivityContainer对象类型,被初始化为null。IActivityContainer也是一个aidl远程接口

inTask:TaskRecord对象类型,被初始化为null。TaskRecord很重要,会经常用到此类,描述一个任务栈,每个任务栈可以包含多个Activity对象,每个TaskRecord对象都有一个当前栈ActivityStack的引用,每个栈可以对应多个TaskRecord对象

除了这些多余的参数,其他参数都是从客户端传递而来。

booleancomponentSpecified=intent.getComponent()!=null;

getComponent方法返回一个ComponentName对象,该对象表示通过intent要启动的组件类,本案例就对应A这个Activity,ComponentName对象一般用包名和类名标识一个组件,因此,componentSpecified为true

intent=newIntent(intent);

根据客户端传递过来的Intent对象重新构建一个Intent对象,这样做是不要破坏客户端传递来的Intent对象

ActivityInfo aInfo=resolveActivity(intent,resolvedType,startFlags,
                profilerInfo,userId);

ActivityInfo resolveActivity(Intent intent,StringresolvedType,intstartFlags,
            ProfilerInfo profilerInfo,intuserId){
    ......
}

resolveActivity方法开始解析Intent对象,返回intent对应的目标Activity类的ActivityInfo对象,ActivityInfo类专门用来描述AndroidManifest.xml中Activity、Receiver组件信息的,本案例返回的就是A这个类对应的信息,ActivityInfo的成员变量name就是类名称,packageName就是包名称,对应本案例分别为com.example.startapptest.A和com.example.startapptest

if(callingUid>=0){
    callingPid=-1;
}elseif(caller==null){
    callingPid=realCallingPid;
    callingUid=realCallingUid;
}else{
    callingPid=callingUid=-1;
}

callingUid传过来时为-1,call又不为空,进程执行else字句callingPid = callingUid = -1;

ActivityContainer container=(ActivityContainer)iContainer;

finalActivityStack stack;
if(container==null||container.mStack.isOnHomeDisplay()){
    stack=getFocusedStack();
}else{
    stack=container.mStack;
}

iContainer为空,那么container也为空,调用getFocusedStack获得当前正在前台的栈,也就是Launcher所在的栈。

if(aInfo!=null&&
                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE)!=0){
    ......
}

aInfo虽然不为空,但aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE却为0,因为没有设置这种属性,因此跳过该if语句,开始执行:

intres=startActivityLocked(caller,intent,resolvedType,aInfo,
                    voiceSession,voiceInteractor,resultTo,resultWho,
                    requestCode,callingPid,callingUid,callingPackage,
                    realCallingPid,realCallingUid,startFlags,options,
                    componentSpecified,null,container,inTask);

finalintstartActivityLocked(IApplicationThread caller,
            Intent intent,StringresolvedType,ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,
            IBinder resultTo,StringresultWho,intrequestCode,
            intcallingPid,intcallingUid,StringcallingPackage,
            intrealCallingPid,intrealCallingUid,intstartFlags,Bundle options,
            booleancomponentSpecified,ActivityRecord[]outActivity,ActivityContainer container,
            TaskRecord inTask){
    ......
}

callingPid:int型变量,看字面意思与pid相关,具体含义后面再看

callingUid:int型变量,看字面意思与uid相关,具体含义后面再看

realCallingPid:启动类所在进程的pid,本案例是Launcher

realCallingUid:启动类所在进程的uid,本案例是Launcher

componentSpecified:为true,表明intent对应的目标Activity类存在

outActivity:ActivityRecord数组名称,初始化为null,ActivityRecord是一个动态生成的对象,代表Activity在历史栈中的记录,ActivityRecord包含了Activity所有信息。

ProcessRecord callerApp=null;
        if(caller!=null){
            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;
            }
        }

mService是ActivityManagerService对象,通过getRecordForAppLocked方法获得启动类所在进程的进程记录对象ProcessRecord。参数caller是IApplicationThread对象,前文提到过,实际是ApplicationThread对象,代表Launcher类的主线程,caller在ActivityManagerService和ActivityThread两个进程之间完成通信,现在终于明白了,为何在startActivity时会带着这样一个参数:服务端通过该参数获得客户端进程信息,该参数起到桥梁作用。

callerApp不为空,分别获得启动类进程的pid和uid保存到callingPid、callingUid中,这个callingPid和之前的realCallingPid获得的值一样,都是Launcher进程pid

        ActivityRecord sourceRecord=null;
        ActivityRecord resultRecord=null;
        if(resultTo!=null){
            sourceRecord=isInAnyStackLocked(resultTo);
            if(DEBUG_RESULTS)Slog.v(
                TAG,"Will send result to "+resultTo+" "+sourceRecord);
            if(sourceRecord!=null){
                if(requestCode>=0&&!sourceRecord.finishing){
                    resultRecord=sourceRecord;
                }
            }
        }

定义了两个ActivityRecord变量sourceRecord、resultRecord,用来对应启动类和目标类。上文提到,resultTo属于IBinder对象,属于启动方的对象。isInAnyStackLocked方法根据启动类的标记resultTo对象在列表栈中找出对应的栈,再在栈顶找到Activity记录保存到sourceRecord中。

finalintlaunchFlags=intent.getFlags();

上文提到,intent一开始在客户端就被设置了FLAG_ACTIVITY_NEW_TASK标志,getFlags方法便取出该标志,保存到launchFlags变量中。

ActivityRecordr=newActivityRecord(mService,callerApp,callingUid,callingPackage,
                intent,resolvedType,aInfo,mService.mConfiguration,resultRecord,resultWho,
                requestCode,componentSpecified,this,container,options);

创建一个ActivityRecord对象,这个ActivityRecord对象具体有什么作用?看看参数具体含义

前4个参数代表了启动类Launcher,第5~7参数(Intent,resolvedType, aInfo)代表了目标类

mService.mConfiguration表示系统配置,resultRecord代表目标类,resultWho代表启动类的一个id号,为空

componentSpecified为true

this:代表当前ActivityStackSupervisor对象

从参数来看,该类既包含启动类的属性,又包含目标类属性,推测该类应该用来表达目标类,后面可以证明。

startActivityLocked方法的作用:获得启动类进程信息、pid、uid,创建ActivityRecord类对象sourceRecord保存启动类信息,创建ActivityRecord对象r,暂时推测代表目标类,具体含义后面分析。进程继续调用:

err=startActivityUncheckedLocked(r,sourceRecord,voiceSession,voiceInteractor,
                startFlags,true,options,inTask);

开始调用下一步操作,第一个参数就是刚才创建的ActivityRecord对象;第二个参数是启动类对象,不为空;

finalintstartActivityUncheckedLocked(ActivityRecordr,ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,intstartFlags,
            booleandoResume,Bundle options,TaskRecord inTask){
    ......
}
finalIntent intent=r.intent;
finalintcallingUid=r.launchedFromUid;

r.intent就是传递而来的intent对象,r.launchedFromUid就是启动类Launcher的uid

finalbooleanlaunchSingleTop=r.launchMode==ActivityInfo.LAUNCH_SINGLE_TOP;
finalbooleanlaunchSingleInstance=r.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE;
finalbooleanlaunchSingleTask=r.launchMode==ActivityInfo.LAUNCH_SINGLE_TASK;

这三个变量代表目标类的启动模式,本案例就是A的启动模式,没有任何设置,默认为Standard模式,因而这三个变量都是false

mUserLeaving=(launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION)==0;

FLAG_ACTIVITY_NO_USER_ACTION:当启动目标Activity时Intent设置了此标志,前台正在行的Activity在暂停之前(执行onPaused方法)不会回调onUserLeaveHint方法。NO_USER_ACTION表示非用户操作,如果设置了此标志,表示非用户行为时不会回调onUserLeaveHint。比如,闹钟响了、来电话了,这属于非用户操作,如果设置了此标志,就不会回调onUserLeaveHint,相反,如果是用户操作行为比如按下HOME按键,返回键等,就会回调onUserLeaveHint。本案例中发送给A的Intent没有设置该标志,mUserLeaving为true,表明不是非用户操作行为。

ActivityRecord notTop=
                (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)!=0?r:null;

Intent没有设置FLAG_ACTIVITY_PREVIOUS_IS_TOP,notTop为空

if(sourceRecord!=null){
            if(sourceRecord.finishing){
                // If the source is finishing, we can't further count it as our source.  This
                // is because the task it is associated with may now be empty and on its way out,
                // so we don't want to blindly throw it in to that task.  Instead we will take
                // the NEW_TASK flow and try to find a task for it. But save the task information
                // so it can be used when creating the new task.
                if((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)==0){
                    Slog.w(TAG,"startActivity called from finishing "+sourceRecord
                            +"; forcing "+"Intent.FLAG_ACTIVITY_NEW_TASK for: "+intent);
                    launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
                    newTaskInfo=sourceRecord.info;
                    newTaskIntent=sourceRecord.task.intent;
                }
                sourceRecord=null;
                sourceStack=null;
            }else{
                sourceStack=sourceRecord.task.stack;
            }
        }else{
            sourceStack=null;
        }

sourceRecord不为空,变量finishing为空,因为此时启动类Launcher还在前台,没有进入到销毁列表中,进程执行else语句,得到启动类所在的栈对象并保存到sourceStack中。

if(((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0&&
                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK)==0)
                ||launchSingleInstance||launchSingleTask){
            // If bring to front is requested, and no result is requested and we have not
            // been given an explicit task to launch in to, and
            // we can find a task that was started with this same
            // component, then instead of launching bring that one to the front.
            if(inTask==null&&r.resultTo==null){
......

Intent没有设置FLAG_ACTIVITY_MULTIPLE_TASK,resultTo和startActivityLocked参数中resultTo不是一个意思,前者是在startActivityLocked函数中创建的ActivityRecord对象resultRecord,代表目标类一方,被初始化为空,而后者代表启动类一方,不能混淆。

ActivityRecord intentActivity=!launchSingleInstance?
                        findTaskLocked(r):findActivityLocked(intent,r.info);
                if(intentActivity!=null){
......

启动A时没有设置启动模式,采用是默认的标准模式,因此launchSingleInstance为false,调用findTaskLocked(r)在当前栈顶中查询是否有目标类,如果有,就返回该类,否则,返回空。因为首次启动A,因此栈中肯定没有A,返回空保存到intentActivity变量中,这样的话,if语句不成立。如果栈中有实例,再次启动时就会执行这段代码。

if(r.packageName!=null){
    ActivityStack topStack=getFocusedStack();
    ActivityRecord top=topStack.topRunningNonDelayedActivityLocked(notTop);
         if(top!=null&&r.resultTo==null){
                if(top.realActivity.equals(r.realActivity)&&top.userId==r.userId){
......
}else{
......
}

目标类包名肯定不为空,执行if条件,getFocusedStack返回当前栈,topRunningNonDelayedActivityLocked返回当前ActivityRecord对象保存到top中,肯定不为空;top.realActivity表示启动类,r.realActivity表示目标类,本案例前者是Launcher,后者是A,两者肯定不相等,因此if语句不成立,跳过此段。如果成立的话,就会在当前栈中找到已存在的实例继续使用。

既然当前栈中没有已存在实例,那么只能新创建一个任务栈,继续看:

booleannewTask=false;
booleankeepCurTransition=false;
TaskRecord taskToAffiliate=launchTaskBehind&&sourceRecord!=null?
         sourceRecord.task:null;
// Should this be considered a new task?
if(r.resultTo==null&&inTask==null&&!addingToTask
         &&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK)!=0){
......

此if语句成立,launchTaskBehind为空,那么taskToAffiliate也为空

newTask=true;
targetStack=adjustStackFocus(r,newTask);

newTask代表新建一个任务的标志,设为true;adjustStackFocus获得一个ActivityStack保存到targetStack变量作为目标类的栈;

if(reuseTask==null){
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo!=null?newTaskInfo:r.info,
                        newTaskIntent!=null?newTaskIntent:intent,
                        voiceSession,voiceInteractor,!launchTaskBehind/* toTop */),
                        taskToAffiliate);
                if(DEBUG_TASKS)Slog.v(TAG,"Starting new activity "+r+" in new task "+
                        r.task);
            }

createTaskRecord创建TaskRecord对象并放到栈顶,然后再放到目标类ActivityRecord的task变量中

targetStack.mLastPausedActivity=null;
targetStack.startActivityLocked(r,newTask,doResume,keepCurTransition,options);
if(!launchTaskBehind){
     // Don't set focus on an activity that's going to the back.
      mService.setFocusedActivityLocked(r,"startedActivity");
}

调用startActivityLocked进行下一步操作

startActivityUncheckedLocked函数非常复杂,最关键的就是查询是否有已存在的TaskRcord作为目标类的任务栈,如果栈中有就复用,否则就创建一个新的TaskRcord对象作为目标类的任务栈。该函数涉及到了FLAG标志,启动模式的判断等,其目的就是找到一个合适的任务栈,为何要找到这个栈,就是因为Activity在执行时以栈这个数据结构来管理。

过程6    frameworks\base\services\core\java\com\android\server\am\ActivityStack.java

finalvoidstartActivityLocked(ActivityRecordr,booleannewTask,
            booleandoResume,booleankeepCurTransition,Bundle options)

第一个参数对应目标类对象记录,newTask为true,表示新建了一个任务栈,doResume为true,keepCurTransition为false。

TaskRecord rTask=r.task;
finalinttaskId=rTask.taskId;

r.task就是在startActivityUncheckedLocked中创建的目标类的RaskRecord对象,取出来保存到rRask变量中

if(!r.mLaunchTaskBehind&&(taskForIdLocked(taskId)==null||newTask)){
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            insertTaskAtTop(rTask);
            mWindowManager.moveTaskToTop(taskId);
}

mLaunchTaskBehind在上文得知为空,taskForIdLocked在历史栈中查询是否含有id号为目标类所在的栈id,如果有,表明目标类之前已经被创建过,现在开始复用该对象,属于非首次启动,否则为首次启动对象,本案例首次启动A,因此,此函数返回null;newTask传递过来为true,if语句成立,调用insertTaskAtTop函数把新创建的TaskRecord对象插入到列表mTaskHistory的尾部,也就是插入到历史栈顶;

if(doResume){
            mStackSupervisor.resumeTopActivitiesLocked(this,r,options);
}

过程7    frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

booleanresumeTopActivitiesLocked(ActivityStack targetStack,ActivityRecord target,
            Bundle targetOptions)

this对象表示当前对象ActivityStack,此ActivityStack是新建的对象,不是Launcher所在的ActivityStack,是在startActivityUncheckedLocked中的adjustStackFocus方法获得的,目的就是把新创建的任务插入到该ActivityStack对象中,这个对象就代表了目标类所属的栈

第二个参数r就表示目标类对象记录,第三个参数依然为null

if(isFrontStack(targetStack)){
        result=targetStack.resumeTopActivityLocked(target,targetOptions);
}

isFrontStack判断新获得的ActivityStack对象位于栈顶,判断为真,执行if语句,调用resumeTopActivityLocked(target, targetOptions)

过程8    frameworks\base\services\core\java\com\android\server\am\ActivityStack.java

finalbooleanresumeTopActivityLocked(ActivityRecord prev,Bundle options){
    ......
}

第一个参数prev表示目标类ActivityRecord对象,第二个传递过来为空

try{
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity=true;
           ......
            result=resumeTopActivityInnerLocked(prev,options);
        }finally{
            mStackSupervisor.inResumeTopActivity=false;
        }

继续调用resumeTopActivityInnerLocked方法,再调用resumeTopActivityInnerLocked

finalbooleanresumeTopActivityInnerLocked(ActivityRecord prev,Bundle options){
    ......
}
// Find the first activity that is not finishing.
finalActivityRecord next=topRunningActivityLocked(null);

// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
finalbooleanuserLeaving=mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving=false;

topRunningActivityLocked方法找到栈顶的ActivityRecord对象,此处对应着A

mStackSupervisor.mUserLeaving的值在过程5中被设置为true,此处取出来赋值给userLeaving,表明是用户操作行为(按下返回键,HOME按键等);无论是true还是false,此处还是再复位一下,重新设置为false

booleandontWaitForPause=(next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING)!=0;
booleanpausing=mStackSupervisor.pauseBackStacks(userLeaving,true,dontWaitForPause);
if(mResumedActivity!=null){
       pausing|=startPausingLocked(userLeaving,false,true,dontWaitForPause);       
}

目标类A没有设置FLAG_RESUME_WHILE_PAUSING标志,dontWaitForPause为false

pauseBackStacks函数返回false赋给pausing变量,mResumedActivity表示当前正在前台运行的Activity,就是Launcher,不为空,进程调用startPausingLocked继续执行

pausing|=startPausingLocked(userLeaving,false,true,dontWaitForPause);

finalbooleanstartPausingLocked(booleanuserLeaving,booleanuiSleeping,booleanresuming,
            booleandontWait){
    ......
}

startPausingLocked开始暂停当前Activity,如果成功,返回true,否则false

4个参数分别为false,false,true,false

ActivityRecord prev=mResumedActivity;
mResumedActivity=null;
mPausingActivity=prev;
mLastPausedActivity=prev;

mResumedActivity代表Launcher,先赋值给prev再置空;prev赋值给mPausingActivity,表明即将要暂停的Activity是Launcher,mLastPausedActivity也赋值为prev,表示刚刚暂停的Activity是哪个

if(prev.app!=null&&prev.app.thread!=null){
    ......
    prev.app.thread.schedulePauseActivity(prev.appToken,prev.finishing,
                        userLeaving,prev.configChangeFlags,dontWait);
    ......
}

prev.app表示Launcher进程信息,不为空;prev.app.thread是一个IApplicationThread对象,对应Launcher也不为空,进程继续调用schedulePauseActivity方法,此处是一个Binder进程间通信,下一步调用到ApplicationThread对象的schedulePauseActivity方法中,ApplicationThread是ActivityThread内部类

过程9    frameworks\base\core\java\android\app\ActivityThread.java

publicfinalvoidschedulePauseActivity(IBinder token,booleanfinished,
                booleanuserLeaving,intconfigChanges,booleandontReport){
            sendMessage(
                    finished?H.PAUSE_ACTIVITY_FINISHING:H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving?1:0)|(dontReport?2:0),
                    configChanges);
}

finished传递过来为false,因为Launcher此时还没有执行生命周期方法onPause()、onDestory(),因此没有进入finishing状态,那么,sendMessage的第一个参数值为H.PAUSE_ACTIVITY

sendMessage把消息发送到队列中等待执行,执行方法是Handler的handleMessage方法,通过命令PAUSE_ACTIVITY可以得到执行程序:

casePAUSE_ACTIVITY:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"activityPause");
    handlePauseActivity((IBinder)msg.obj,false,(msg.arg1&1)!=0,msg.arg2,
             (msg.arg1&2)!=0);
    maybeSnapshot();
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;

继续调用handlePauseActivity方法

privatevoidhandlePauseActivity(IBinder token,booleanfinished,
            booleanuserLeaving,intconfigChanges,booleandontReport){
    ......
}

finished为false,userLeaving传递过来为true,configChanges为0,dontReport为false

ActivityClientRecordr=mActivities.get(token);

token对应启动类Launcher,此处获得Launcher的ActivityRecord对象

if(userLeaving){
        performUserLeavingActivity(r);
}

调用performUserLeavingActivity方法,performUserLeavingActivity的最终调用过程为:

performUserLeavingActivity—->

mInstrumentation.callActivityOnUserLeaving(r.activity) —->

activity.performUserLeaving() —->

onUserInteraction()

onUserLeaveHint()

意味着,如果是用户操作的主动行为,比如返回按键,遥控器上下左右按键,HOME按键灯,会调用Activity的

onUserInteraction和onUserLeaveHint方法,如果是按键,触摸、轨迹球被分发到Activity时,onUserInteraction会被回调;onUserLeaveHint的作用是当Activity即将进入到后台前被回调,起到提示作用

performUserLeavingActivity执行完后,进程继续调用

performPauseActivity(token,finished,r.isPreHoneycomb());

finalBundle performPauseActivity(ActivityClientRecordr,booleanfinished,
            booleansaveState){
      .....
      mInstrumentation.callActivityOnPause(r.activity);
      r.paused=true;
}

performPauseActivity方法中继续调用callActivityOnPause方法,参数r.activity代表启动类Launcher

过程9.1    frameworks\base\core\java\android\app\Instrumentation.java

publicvoidcallActivityOnPause(Activity activity){
        activity.performPause();
}

过程9.1.1    frameworks\base\core\java\android\app\Activity.java

finalvoidperformPause(){
        mDoReportFullyDrawn=false;
        mFragments.dispatchPause();
        mCalled=false;
        onPause();
        mResumed=false;
    ......
        mResumed=false;
}

最终调用到Activity的performPause方法,再调用生命周期方法onPause()意味着启动类处于暂停状态了,这一步执行完后返回到performPauseActivity中,执行r.paused = true把启动类的ActivityClientRecord的paused置为true,表示启动类此时已经处于暂停状态了。再返回到handlePauseActivity中,继续执行performPauseActivity后面的语句

ActivityManagerNative.getDefault().activityPaused(token);

这一步通过Binder进程间通信机制进入到ActivityManagerService的activityPaused方法中

过程9.2    frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

publicfinalvoidactivityPaused(IBinder token){
    ......
    stack.activityPausedLocked(token,false);
    .....
}

过程10    frameworks\base\services\core\java\com\android\server\am\ActivityStack.java

finalvoidactivityPausedLocked(IBinder token,booleantimeout){
    ......
}

mPausingActivity表示启动类Launcher,r是Launcher的ActivityRecord对象,if条件为真,进程继续调用completePauseLocked(true)方法

privatevoidcompletePauseLocked(booleanresumeNext){
    ......
}

既然启动类都已经暂停了,那下一步工作是不是就是把目标类启动起来呢?如果是的话,应该会执行生命周期onResume方法,这只是猜测,具体详细看方法的执行过程

参数resumeNext传递过来为true

prev.finishing属性为false,这个属性一直没有设置

mPausingActivity = null;

如果启动类已经stop,就把mPausingActivity设为null

进程继续执行到:

finalActivityStack topStack=mStackSupervisor.getFocusedStack();
if(!mService.isSleepingOrShuttingDown()){
        mStackSupervisor.resumeTopActivitiesLocked(topStack,prev,null);
}

当前系统处于非睡眠和关机状态,if条件为真,进程开始调用resumeTopActivitiesLocked方法

过程11    frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

booleanresumeTopActivitiesLocked(ActivityStack targetStack,ActivityRecord target,
            Bundle targetOptions){
    ......
}

要清楚方法具体做了什么,一定要先弄清楚参数的含义

形参targetStack的实参是topStack,通过mStackSupervisor.getFocusedStack获得,即当前获得焦点的栈,此处,启动类已经暂停,那么当前栈就是目标类所在的栈,prev是启动类

又调用了resumeTopActivityLocked方法

if(isFrontStack(targetStack)){
         result=targetStack.resumeTopActivityLocked(target,targetOptions);
}

过程12    frameworks\base\services\core\java\com\android\server\am\ActivityStack.java

finalbooleanresumeTopActivityLocked(ActivityRecord prev,Bundle options){
    ......
}

继续调用resumeTopActivityInnerLocked方法

finalbooleanresumeTopActivityInnerLocked(ActivityRecord prev,Bundle options){
    ......
}

再次进入到此方法时,mResumedActivity为空,因为这是在过程8中startPausingLocked方法内设置的,表明启动类Launcher已经不在是当前运行的Activity,因此

if(mResumedActivity!=null){
            if(DEBUG_STATES)Slog.d(TAG,"resumeTopActivityLocked: Pausing "+mResumedActivity);
            pausing|=startPausingLocked(userLeaving,false,true,dontWaitForPause);
}

这个语句就不再成立,进程跳过此句继续执行

if(next.app!=null&&next.app.thread!=null){
    ......
    mStackSupervisor.startSpecificActivityLocked(next,true,false);
    ......
}else{
    ......
    mStackSupervisor.startSpecificActivityLocked(next,true,false);
    ......
}

next就是目标类A,此时A的一些栈等信息已经构建,但是A得进程还没有创建,正常情况下,启动一个新的应用程序一般会创建一个新的进程,应用程序在此进程中执行,特殊情况下可以通过AndroidManifest中process属性执行指定应用程序在某个进程中执行,本文没有设置process属性,默认为启动一个新的进程,本文后面会分析到。由此可知,A还没有进程信息,if语句不成立,进程转到else语句执行

过程13    frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

voidstartSpecificActivityLocked(ActivityRecordr,
            booleanandResume,booleancheckConfig){
    ......
}
ProcessRecord app=mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid,true);
if(app!=null&&app.thread!=null){
    ......
    realStartActivityLocked(r,app,andResume,checkConfig);
    ......
}
mService.startProcessLocked(r.processName,r.info.applicationInfo,true,0,
                "activity",r.intent.getComponent(),false,false,true);

此时A进程还没有创建,所以app为空,跳过if语句,开始调用startProcessLocked方法

假如A的应用程序已经启动,然后在A中启动B,B是A应用程序的一个Activity,那么此时进程已经创建,app就不会为空,进程会调用realStartActivityLocked方法

过程14    frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

finalProcessRecord startProcessLocked(StringprocessName,
            ApplicationInfo info,booleanknownToBeDead,intintentFlags,
            StringhostingType,ComponentName hostingName,booleanallowWhileBooting,
            booleanisolated,booleankeepIfLarge){
        returnstartProcessLocked(processName,info,knownToBeDead,intentFlags,hostingType,
                hostingName,allowWhileBooting,isolated,0/* isolatedUid */,keepIfLarge,
                null/* ABI override */,null/* entryPoint */,null/* entryPointArgs */,
                null/* crashHandler */);
    }
finalProcessRecord startProcessLocked(StringprocessName,ApplicationInfo info,
            booleanknownToBeDead,intintentFlags,StringhostingType,ComponentName hostingName,
            booleanallowWhileBooting,booleanisolated,intisolatedUid,booleankeepIfLarge,
            StringabiOverride,StringentryPoint,String[]entryPointArgs,Runnable crashHandler){
    
    ......
    

}

该方法中会为A创建ProcessRecord信息,然后继续调用

startProcessLocked(
                app,hostingType,hostingNameStr,abiOverride,entryPoint,entryPointArgs);
privatefinalvoidstartProcessLocked(ProcessRecord app,StringhostingType,
            StringhostingNameStr,StringabiOverride,StringentryPoint,String[]entryPointArgs){
    ......
    Process.ProcessStartResult startResult=Process.start(entryPoint,
    app.processName,uid,uid,gids,debugFlags,mountExternal,
    app.info.targetSdkVersion,app.info.seinfo,requiredAbi,instructionSet,
    app.info.dataDir,entryPointArgs);
    ......
}

此方法中会调用进程的start方法创建一个新的进程,具体是通过zygote进程的来fork一个新的进程,成为子进程,子进程共享父进程资源,几乎和父进程一样。当子进程创建好后,系统会分配一个进程号PID给新进程并返回,否则抛出异常

publicstaticfinalProcessStartResult start(finalStringprocessClass,
                                  finalStringniceName,
                                  intuid,intgid,int[]gids,
                                  intdebugFlags,intmountExternal,
                                  inttargetSdkVersion,
                                  StringseInfo,
                                  Stringabi,
                                  StringinstructionSet,
                                  StringappDataDir,
                                  String[]zygoteArgs){
    ......
}

第一个参数processClass为新创建的进程的入口类即android.app.ActivityThread.java

niceName:新创建的进程的进程名字,用ps命令可以查看到该名字,一般情况下,应用程序的进程名就是包名

如果进程创建成功,待方法start执行完后,系统就会转到ActivityThread.java的main方法入口开始执行,注意这个流程,和我们通常看到的方法调用方法是不一样的。

过程15    frameworks\base\core\java\android\app\ActivityThread.java

publicstaticvoidmain(String[]args){
        ......

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        ActivityThread thread=newActivityThread();
        thread.attach(false);

        if(sMainThreadHandler==null){
            sMainThreadHandler=thread.getHandler();
        }

        if(false){
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG,"ActivityThread"));
        }

        Looper.loop();

        thrownewRuntimeException("Main thread loop unexpectedly exited");
}

prepareMainLooper方法创建了looper对象和MessageQueue消息队列;创建了并初始化ActivityThread对象,同时也创建并初始化了ApplicationThread对象mAppThread

thread.attach(false);
privatevoidattach(booleansystem){
    ......
    finalIActivityManager mgr=ActivityManagerNative.getDefault();
    mgr.attachApplication(mAppThread);
}

获得ActivityManagerProxy对象,调用该对象的attachApplication方法,通过binder通信,最终调用到ActivityManagerService的attachApplication方法

过程16    frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

publicfinalvoidattachApplication(IApplicationThread thread){
        synchronized(this){
    ......
        }
}
privatefinalbooleanattachApplicationLocked(IApplicationThread thread,
            intpid){
    ......
}

先通过pid获得ProcessRecord对象,该对象上一步创建过,不为空

app.makeActive(thread,mProcessStats);
app.curAdj=app.setAdj=-100;
app.curSchedGroup=app.setSchedGroup=Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground=null;
updateProcessForegroundLocked(app,false,false);
app.hasShownUi=false;
app.debugging=false;
app.cached=false;
app.killedByAm=false;

初始化该ProcessRecord对象

// See if the top visible activity is waiting to run in this process...
        if(normalMode){
            try{
                if(mStackSupervisor.attachApplicationLocked(app)){
                    didSomething=true;
                }
            }catch(Exceptione){
                Slog.wtf(TAG,"Exception thrown launching activities in "+app,e);
                badApp=true;
            }
}

这段话就是真正开始启动目标Activity了,本案例就是A

注:在这段话后面分别有:

// Find any services that should be running in this process...
        if(!badApp){
            try{
                Slog.i("zhulf","---------------------601");
                didSomething|=mServices.attachApplicationLocked(app,processName);
            }catch(Exceptione){
                Slog.wtf(TAG,"Exception thrown starting services in "+app,e);
                badApp=true;
            }
        }

        // Check if a next-broadcast receiver is in this process...
        if(!badApp&&isPendingBroadcastProcessLocked(pid)){
            try{
                didSomething|=sendPendingBroadcastsLocked(app);
            }catch(Exceptione){
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG,"Exception thrown dispatching broadcasts in "+app,e);
                badApp=true;
            }
}

用来启动Service、发送广播,此处作为一个备注,如果要分析启动Service、广播,研究这两段语句,本文只研究启动Activity,因此,详细看attachApplicationLocked方法

过程17    frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

booleanattachApplicationLocked(ProcessRecord app)throwsRemoteException{
    ......
}
if(realStartActivityLocked(hr,app,true,true)){
        didSomething=true;
}
finalbooleanrealStartActivityLocked(ActivityRecordr,
            ProcessRecord app,booleanandResume,booleancheckConfig)
            throwsRemoteException{
    ......
}

hr就是目标类ActivityRecord对象,app是进程名字

mService.updateLruProcessLocked(app,true,null);
mService.updateOomAdjLocked();

调整进程LRU算法;参与管理进程

app.thread.scheduleLaunchActivity(newIntent(r.intent),r.appToken,
                    System.identityHashCode(r),r.info,newConfiguration(mService.mConfiguration),
                    r.compat,r.launchedFromPackage,r.task.voiceInteractor,app.repProcState,
                    r.icicle,r.persistentState,results,newIntents,!andResume,
                    mService.isNextTransitionForward(),profilerInfo);

app.thrad是IApplicationThread对象,此处就是ApplicationThreadProxy对象接口,这里也是Binder通信过程,调用ApplicationThreadProxy的scheduleLaunchActivity方法,通过binder通信转到ApplicationThread对象的scheduleLaunchActivity方法,该方法在ActivityThread对象中

过程18    frameworks\base\core\java\android\app\ActivityThread.java

publicfinalvoidscheduleLaunchActivity(Intent intent,IBinder token,intident,
                ActivityInfo info,Configuration curConfig,CompatibilityInfo compatInfo,
                Stringreferrer,IVoiceInteractor voiceInteractor,intprocState,Bundle state,
                PersistableBundle persistentState,List<ResultInfo>pendingResults,
                List<ReferrerIntent>pendingNewIntents,booleannotResumed,booleanisForward,
                ProfilerInfo profilerInfo){
    ....
}

该方法创建了目标类对应的ActivityClientRecord对象,而后初始化该对象,作为sendMessage参数发送到消息队列待处理

caseLAUNCH_ACTIVITY:{
                    finalActivityClientRecordr=(ActivityClientRecord)msg.obj;
                    r.packageInfo=getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo,r.compatInfo);
                    handleLaunchActivity(r,null);
                    }
privatevoidhandleLaunchActivity(ActivityClientRecordr,Intent customIntent){
    ......
}

该方法分为两个部分,先调用performLaunchActivity,再调用handleResumeActivity,最后还有finishActivity

先看performLaunchActivity

privateActivity performLaunchActivity(ActivityClientRecordr,Intent customIntent){
    ......
}
ActivityInfo aInfo=r.activityInfo;

从目标类ActivityClientRecord对象中取出ActivityInfo对象,ActivityInfo对象包含了Activity、receiver对象信息

ComponentName component=r.intent.getComponent();

再根据Intent获得组件对象component,组件包含了启动类名称和包名称

java.lang.ClassLoader cl=r.packageInfo.getClassLoader();
activity=mInstrumentation.newActivity(
                    cl,component.getClassName(),r.intent);

通过Java反射机制找到目标类文件,再创建目标类的一个对象赋值给activity。从此处可知,原来Android中Activity对象是在启动时创建的,系统已经帮助程序员写好了new Activity对象的动作,无需程序员自行new对象,这解决了一开始学习android时总是搞不清楚Activity对象是从什么时候创建的的困惑,因此,Android并不关注组件的创建过程,而把关注点落在了组件的生命周期上。

Application app=r.packageInfo.makeApplication(false,mInstrumentation);

makeApplication方法也是利用反射机制找到应用程序Application类并创建一个对象,并调用Application对象的onCreate方法,这就是为什么应用一启动后,Application的onCreate比Activity的onCreate先执行的原因!

Context appContext=createBaseContextForActivity(r,activity);
activity.attach(appContext,this,getInstrumentation(),r.token,
                        r.ident,app,r.intent,r.activityInfo,title,r.parent,
                        r.embeddedID,r.lastNonConfigurationInstances,config,
                        r.referrer,r.voiceInteractor);

createBaseContextForActivity方法中会调用createActivityContext创建ContextImpl对象,ContextImpl实现了Context,也就同时创建了上下文管理者Context对象,这也解决了为什么在写程序时总是能够获得Context对象的原因

attach方法把Context对象、Instrumentation对象等和Activity关联起来

mInstrumentation.callActivityOnCreate(activity,r.state);

通过Instrumentation对象的callActivityOnCreate方法进入到Instrumentation对象中,Instrumentation对象就是监控所有用户和系统之间的交互操作,比如onCreate、onResume等

过程19    frameworks\base\core\java\android\app\Instrumentation.java

publicvoidcallActivityOnCreate(Activity activity,Bundle icicle){
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
}

继续调用performCreate方法

过程20    frameworks\base\core\java\android\app\Activity.java

finalvoidperformCreate(Bundle icicle){
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
}

最终调用Activity的onCreate方法开始生命周期

再返回到handleLaunchActivity中,进程继续执行到handleResumeActivity方法

ActivityClientRecordr=performResumeActivity(token,clearHide);
r.activity.performResume();
mInstrumentation.callActivityOnResume(this);
activity.onResume();

这四步写在一个代码段,可以看到最终调用了Activity的onResume方法,目标类A启动起来了并成为可见状态

到此处为止,在Launcher中启动Activity的过程就分析完了。

整个过程相当复杂,涉及到很多动态对象,进程间通信,栈的管理等,可以不必要理解每句代码,但是清楚整个流程做了哪些核心的动作是有必要的:

1.  过程5

resolveActivity方法中调用了包管理器PackageManager的resolveIntent方法解析启动目标类的Intent对象,获得解析后的对象ActivityInfo,为何要获得这个对象,这个对象有有什么作用?

在AndroidManifest.xml中Activity和receiver标签包含了很多属性,比如主题、启动模式、屏幕方向,输入法设置,进程名称等,ActivityInfo就是对应目标类Activity的一个动态对象,该对象包含了这些属性信息。该对象的作用用来构建目标类对应的ActivityRecord对象,该对象也是一个动态对象,是历史栈中的一条记录,在内存中对应目标类。

这样就明白一个问题:启动activity时有显示和隐式,对于隐式方式,只需要在目标类中intetn-filter中增加一个action,然后启动类通过这个action即可启动目标类,这是如何做到的?实际上是通过包管理器PackageManager解析intent,查找到匹配的action对应的目标类的。

2. 过程8

startPausingLocked方法是进入到暂停启动类过程的标志,逐步调用prev.app.thread.schedulePauseActivity,然后又binder通信进入到ApplicationThread对象的schedulePauseActivity方法,在此方法中,发送消息给启动类Launcher主线程ActivityThread,ActivityThread利用handler循环处理消息,调用handlePauseActivity方法处理,最终调用到Activity的生命周期方法onPause暂停启动类

3.  过程14

Process对象的start方法开启了一个新的进程作为目标类的主线程,由此,目标类开始从ActivityThread的main方法开支执行,然后由

mgr.attachApplication(mAppThread);

语句通过binder通信进入到ActivityManagerService中,并传递了ApplicationThread对象,该对象传入到ActivityManagerService中后构建目标类进程信息,然后ActivityManagerService负责启动目标类,最终通过该对象又通过Binder通信返回到ApplicationThread对象中,然后ApplicationThread对象又发送消息给目标类主线程ActivityThread对象,该对象循环处理来自ActivityManagerService的消息,进而调用Activity的生命周期方法onCreate、onResume。其中,IApplicationThread远程接口对象起着非常关键作用,他在主线程对象ActivityThread与Activity管理器ActivityManagerService对象之间起着通信桥梁作用。

ActivityManagerService是Activity Manager(注意,分开大写,代表Framework层的核心模块,该模块包含了ActivityManagerService、ActivityStack、Binder接口等)的核心部分,负责启动Activity、Service、发送Broadcast Receiver、启动ContentProvider;调整进程调度算法,管理任务栈、检查权限等一些列核心功能。

2. 调用startActivity启动一个Activity

在应用程序内启动Activity,和应用程序外启动最根本的不同在于不会新创建进程,也就是说,过程13中,不会执行startProcessLocked方法,而执行realStartActivityLocked方法,过程13~过程16可以省略不看,此时在同一个进程中;除此之外,就是栈的获取不一样,用startActivity方法启动可能不会新建栈,直接使用已有的栈,而Launcher启动时一般会新建栈。

3. 命令am start启动

这种方法适合调试时使用,在串口中直接采用

am start -n xxx/.yyy

即可启动应用程序,包名是xxx,入口类名是yyy

am 这个可执行程序对应的源码目录位置:

framework\base\cmds\am\src\com\android\commands\am\Am.java

当执行这条命令时,先从main方法开始执行

publicstaticvoidmain(String[]args){
        (newAm()).run(args);
}

Am继承了BaseCommand类,run方法在BaseCommand中定义,在run方法中又调用了onRun()方法,系统运行时具体类型是Am,这样就调到了Am的onRun方法。onRun中先执行:

mAm=ActivityManagerNative.getDefault();

获得ActivityManagerService的代理类ActivityManagerProxy的一个对象

Stringop=nextArgRequired();
if(op.equals("start")){
     runStart();
}

判断参数是否有start这个字符串,如果有,就调用runStart方法,本文启动Activity当然含有start参数

在runStart方法中,会执行这一句

res=mAm.startActivityAsUser(null,null,intent,mimeType,
                        null,null,0,mStartFlags,profilerInfo,null,mUserId);

这一步会继续调用ActivityStackSupervisor的startActivityMayWait方法,与上文的“过程4”一样,后面的步骤基本上差不多。

不管哪种方式启动,在服务端的操作基本上相同,区别就在于是否复用当前栈还是新创建一个栈,是否新建一个进程作为目标类的进程等;在客户端,区别在于启动Activity的方式不同,第三种命令启动方式缺少了startActivity部分。

同分类推荐文章

  1. 「置顶」我做了什么 (2026-05-05 12:13:28)
  2. 万字长文推演:手机不再从 App 开始,Agent OS 如何接管任务入口 (2026-04-28 14:57:22)
  3. Android Perfetto 系列 10 - Binder 调度与锁竞争 (2025-11-16 15:33:30)

查看更多 移动开发 文章 →

建议继续学习

  1. 情绪版(Mood board)操作流程的新思考 (累计阅读 41,756)
  2. android 开发入门 (累计阅读 19,530)
  3. Android 连接SSID隐藏网络以及 LEAP 认证的方法 (累计阅读 9,539)
  4. 让安卓手机通过代理翻墙的方法 (累计阅读 9,117)
  5. 手机产品设计方向 (累计阅读 7,954)
  6. 实时监控Android设备网络封包 (累计阅读 6,558)
  7. Eclipse开发Android应用程序入门:重装上阵 (累计阅读 6,463)
  8. 基于 PhoneGap 与 Java 开发的 Android 应用的性能对比 (累计阅读 6,411)
  9. Android用户界面设计:表格布局 (累计阅读 6,186)
  10. Windows下使用VMware安装Android (累计阅读 5,633)