Android应用程序启动过程源代码分析

前文简要介绍了Android应用程序的Activity的启动过程。在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程,本文将详细分析应用程序框架层的源代码,了解Android应用程序的启动过程。

在上一篇文章Android应用程序的Activity启动过程简要介绍和学习计划中,我们举例子说明了启动Android应用程序中的Activity的两种情景,其中,在手机屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来。这种启动方式的特点是会启动一个新的进程来加载相应的Activity。这里,我们继续以这个例子为例来说明Android应用程序的启动过程,即MainActivity的启动过程。

下面详细分析每一步是如何实现的。

Step 1. Launcher.startActivitySafely

在Android系统中, 应用程序是由Launcher 启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。

Launcher的源代码工程在packages/apps/Launcher2目录下,负责启动其它应用程序的源代码实现在src/com/android/launcher2/Launcher.java文件中:

/**
* Default launcher application.
*/
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) {
            ......
        } else if (v == mHandleView) {
            ......
        }
    }

    void startActivitySafely(Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            startActivity(intent);
        } catch (ActivityNotFoundException e) {
            ......
        } catch (SecurityException e) {
            ......
        }
    }

    ......

}

回忆一下前面一篇文章Android应用程序的Activity启动过程简要介绍和学习计划说到的应用程序Activity,它的默认Activity是MainActivity,这里是AndroidManifest.xml文件中配置的:

<activity android:name=".MainActivity"  
      android:label="@string/app_name">  
       <intent-filter>  
        <action android:name="android.intent.action.MAIN" />  
        <category android:name="android.intent.category.LAUNCHER" />  
    </intent-filter>  
</activity>

因此,这里的intent包含的信息为:action = "android.intent.action.Main"category="android.intent.category.LAUNCHER", cmp=”shy.luo.activity/.MainActivity”,表示它要启动的Activity为shy.luo.activity.MainActivity。Intent.FLAG_ACTIVITY_NEW_TASK表示要在一个新的Task中启动这个Activity,注意,Task是Android系统中的概念,它不同于进程Process的概念。简单地说,一个Task是一系列Activity的集合,这个集合是以堆栈的形式来组织的,遵循后进先出的原则。事实上,Task是一个非常复杂的概念。这里,我们只要知道,这个MainActivity要在一个新的Task中启动就可以了。

Step 2. Activity.startActivity

在Step 1中,Launcher继承于Activity类,而Activity类实现了startActivity(),因此,这里就调用了Activity.startActivity函数,它实现在frameworks/base/core/java/android/app/Activity.java文件中:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {

    ......

    @Override
    public void startActivity(Intent intent) {
        startActivityForResult(intent, -1);
    }

}

这个函数实现很简单,它调用startActivityForResult来进一步处理,第二个参数传入-1表示不需要这个Actvity结束后的返回结果。

Step 3. Activity.startActivityForResult

这个函数也是实现在frameworks/base/core/java/android/app/Activity.java文件中:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {

    ......

    public void startActivityForResult(Intent intent, int requestCode) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode);
            ......
        } else {
            ......
        }

    ......

}

这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。
这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程,我们在Android系统在新进程中启动自定义服务过程(startService)的原理分析一文中已经介绍过了。这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。这里我们需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。

这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。

Step 4. Instrumentation.execStartActivity

这个函数定义在frameworks/base/core/java/android/app/Instrumentation.java文件中:

public class Instrumentation {

    ......

    public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, Activity target,
    Intent intent, int requestCode) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            ......
        }
        try {
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                null, 0, token, target != null ? target.mEmbeddedID : null,
                requestCode, false, false);
            ......
        } catch (RemoteException e) {
        }
        return null;
    }

    ......

}

这里的 ActivityManagerNative.getDefault 返回 ActivityManagerService 的远程接口,即 ActivityManagerProxy 接口,具体可以参考Android系统在新进程中启动自定义服务过程(startService)的原理分析一文。
这里的intent.resolveTypeIfNeeded返回这个intent的MIME类型,在这个例子中,没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。

这里的target不为null,但是target.mEmbddedID为null,我们不用关注。

Step 5. ActivityManagerProxy.startActivity

这个函数定义在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:

这里的参数比较多,先整理一下。从上面的调用可以知道,这里的参数resolvedType、grantedUriPermissions和resultWho均为null;参数caller为ApplicationThread类型的Binder实体;参数resultTo为一个Binder实体的远程接口,我们先不关注它;参数grantedMode为0,我们也先不关注它;参数requestCode为-1;参数onlyIfNeeded和debug均空false。

Step 6. ActivityManagerService.startActivity

上一步Step 5通过Binder驱动程序就进入到ActivityManagerService的startActivity函数来了,它定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

这里只是简单地将操作转发给成员变量mMainStack的startActivityMayWait函数,这里的mMainStack的类型为ActivityStack。

Step 7. ActivityStack.startActivityMayWait

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:

注意,从Step 6传下来的参数outResult和config均为null,此外,表达式(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0为false,因此,这里忽略了无关代码。



MainActivity就启动起来了,整个应用程序也启动起来了。
整个应用程序的启动过程要执行很多步骤,但是整体来看,主要分为以下五个阶段:

   一. Step1 - Step 11:Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;

   二. Step 12 - Step 16:ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;

   三. Step 17 - Step 24:Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行;

   四. Step 25 - Step 27:ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;

   五. Step 28 - Step 35:ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。

这里不少地方涉及到了Binder进程间通信机制,相关资料请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。

这样,应用程序的启动过程就介绍完了,它实质上是启动应用程序的默认Activity,在下一篇文章中,我们将介绍在应用程序内部启动另一个Activity的过程,即新的Activity与启动它的Activity将会在同一个进程(Process)和任务(Task)运行,敬请关注。

转载自:http://blog.csdn.net/luoshengyang/article/details/6689748(有删减)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值