6.3 startActivity分析

本节将重点分析Activity的启动过程,它是五条线中最难分析的一条,只要用心,相信读者能啃动这块“硬骨头”。

6.3.1 从am说起

am和pm(见4.4.2节)一样,也是一个脚本,它用来和AMS交互,如启动Activity、启动Service、发送广播等。其核心文件在Am.java中,代码如下:

[—>Am.java:main]


public static void main(String[]args){

try{

(new Am()).run(args);//构造一个am对象,并调用run函数

}……

}


am的用法很多,读者可通过adb shell登录手机,然后执行am,这样就能获取它的用法。

利用am启动一个activity的方法如下:


am start[-D][-W][-P<FILE>][—start-profiler<FILE>][-S]<INTENT>


其中:

方括号中的参数为可选项,尖括号中的参数为必选项。

<INTENT>参数有很多,主要是用于设置Intent的各项参数。

假设已知某个Activity的ComponentName(package名和Activity的Class名),启动这个Activity的相应命令如下:


am start-W-n com.dfp.test/.TestActivity


其中,-W选项表示am将会等目标Activity启动后才返回,-n表示后面的参数用于设置Intent的Component。就本例而言,com.dfp.test为Package名,.TestActivity为该Package下对应的Activity类名,所以将要启动的Activity的全路径名为com.dfp.test.TestActivity。

现在就以上面的命令为例来分析am的run函数,代码如下:

[—>Am.java:run]


private void run(String[]args)throws Exception{

mAm=ActivityManagerNative.getDefault();

mArgs=args;

String op=args[0];mNextArg=1;

if(op.equals("start"))runStart();//用于启动Activity

else if……//处理其他参数

}


runStart函数用于处理Activity启动请求,其代码如下:

[—>Am.java:runStart]


private void runStart()throws Exception{

Intent intent=makeIntent();

String mimeType=intent.getType();

//获取mimeType,

if(mimeType==null&&intent.getData()!=null

&&"content".equals(intent.getData().getScheme())){

mimeType=mAm.getProviderMimeType(intent.getData());

}

if(mStopOption){

……//处理-S选项,即先停止对应的Activity,再启动它

}

//FLAG_ACTIVITY_NEW_TASK这个标签很重要

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ParcelFileDescriptor fd=null;

if(mProfileFile!=null){

try{……//处理-P选项,用于性能统计

fd=ParcelFileDescriptor.open(……)

}……

}

IActivityManager.WaitResult result=null;

int res;

if(mWaitOption){//mWaitOption控制是否等待启动结果,如果有-W选项,则该值为true

//调用AMS的startActivityAndWait函数

result=mAm.startActivityAndWait(null, intent, mimeType,

null,0,null, null,0,false, mDebugOption,

mProfileFile, fd, mProfileAutoStop);

res=result.result;

}……

……//打印结果

}


am最终将调用AMS的startActivityAndWait函数来处理这次启动请求。下面将深入到AMS内部去继续这次旅程。

提示 为什么选择从am来分析Activity的启动呢?这是因为如果选择从一个Activity来分析如何启动另一个Activity,则将给人一种鸡生蛋、蛋孵鸡的感觉,故此处选择从am入手。除此之外,从am来分析Activity的启动也是Activity启动分析中相对简单的一条路线。