android activity 启动过程分析(source code 4.4)

说实话,android source code从2.3到4.4变化是蛮多的,尤其是media部分,虽然总的框架是没有多大变化,但是找起代码来看还是挺麻烦的。在android里面最受伤的是使用了java,jni,jvm,Nativity c++等等,各种设计模式横行,当然在学习源码过程中也意识了编程语言基础,数据结构,设计模式的重要性。

android source code 经典的地方:

1. 大量使用了各种设计模式如单例模式,装饰模式,工程工厂模式,适配器模式等等。

2. 使用了binder驱动进行了IPC通信。

3. 重新设计了消息处理机制。

4. 加入了强弱指针管理。

5. 设计了activity安全的权限管理。

6. 对应用开发者可扩展,开发维护做出突出的贡献。

7. 使用了JNI技术。

8. 优化了电源管理服务。

。。。。。等等

当然,也有缺点地方。

1.  android启动慢。

因为使用了jni,jvm原因需要加载很多类及类库,和各种服务的启动。为了用户体验,使用了sureface。

上述启动完后还要启动launcher,扫描各个应用信息等等。

2.  android 是为嵌入式产品而开发的。实际上内存使用效果来看不是很理想,容易产生碎片,导致android使用越用越慢。

3.  主题定制少,缺乏大型游戏。

4.  app常驻内存导致无法长时间待机。

好吧,不要抱怨那么多了,生活已经够无奈的了。开始分析下吧。

1.  在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程。即在桌面程序(launcher)启动时候,扫描各个app信息,在设备屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来。这种启动方式的特点是会启动一个新的进程来加载相应的Activity。

2.  由上可知:默认启动activity是通过launcher(onClick方法)来启动的,其实就是解析AndroidManifest.xml中的activity标签及<intent-filter>标签。然后通过startActivitySafely方法启动activity。

 1 Launcher.java (e:\baiduyundownload\intel_x86_sysimg_4.4_source_files_20131206\intel_x86_sysimg_4.4_source_files_20131206\packages\apps\launcher2\src\com\android\launcher2)
 2
 3     public void onClick(View v) {
 4         // Make sure that rogue clicks don‘t get through while allapps is launching, or after the
 5         // view has detached (it‘s possible for this to happen if the view is removed mid touch).
 6         if (v.getWindowToken() == null) {
 7             return;
 8         }
 9
10         if (!mWorkspace.isFinishedSwitchingState()) {
11             return;
12         }
13
14         Object tag = v.getTag();
15         if (tag instanceof ShortcutInfo) {
16             // Open shortcut
17             final Intent intent = ((ShortcutInfo) tag).intent;
18             int[] pos = new int[2];
19             v.getLocationOnScreen(pos);
20             intent.setSourceBounds(new Rect(pos[0], pos[1],
21                     pos[0] + v.getWidth(), pos[1] + v.getHeight()));
22
23             boolean success = startActivitySafely(v, intent, tag);
24
25             if (success && v instanceof BubbleTextView) {
26                 mWaitingForResume = (BubbleTextView) v;
27                 mWaitingForResume.setStayPressed(true);
28             }
29         } else if (tag instanceof FolderInfo) {
30             if (v instanceof FolderIcon) {
31                 FolderIcon fi = (FolderIcon) v;
32                 handleFolderClick(fi);
33             }
34         } else if (v == mAllAppsButton) {
35             if (isAllAppsVisible()) {
36                 showWorkspace(true);
37             } else {
38                 onClickAllAppsButton(v);
39             }
40         }
41 }
    boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
            success = startActivity(v, intent, tag);
        } 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);
        }
        return success;
    }
    boolean startActivity(View v, Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {
            // Only launch using the new animation if the shortcut has not opted out (this is a
            // private contract between launcher and may be ignored in the future).
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);       //useLaunchAnimation表示是否使用点击Launcher桌面上的图标,会先有图标放大的动画,然后才进入应用,2.3之前是没有这个选择的。
            if (useLaunchAnimation) {
                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
                        v.getMeasuredWidth(), v.getMeasuredHeight());

                startActivity(intent, opts.toBundle());
            } else {
                startActivity(intent);
            }
            return true;
        } 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);
        }
        return false;
    }

  上面的

startActivity(intent, opts.toBundle());在launcher.java中没有找到定义,实际上是在launcher的基类中定义的,需要转到activity.java中查找定义。

Activity.java (base\core\java\android\app)

    @Override
    public void startActivity(Intent intent, Bundle options) {
        if (options != null) {      //第二个参数传入-1表示不需要这个Actvity结束后的返回结果。
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (mParent == null) {      //这里的mParent肯定为null,因为是从launcher启动进来的,肯定没有父activity。      //这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。      //这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程,这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。这里我们需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。      //这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
           .......
}
Instrumentation.java (base\core\java\android\app)
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        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 {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();        //这里的ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口,跟进去就知道了(IActivityManager)。        //intent.resolveTypeIfNeeded返回这个intent的MIME类型,一般没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }
ActivityManagerNative.java (base\core\java\android\app)
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {//这里已经非常接近核心了,1. 构造parcel data包和reply包,将相关要启动的intent数据打进去,然后通过远程对象mRemote的transact方法(binder IPC)投递到服务端( ActivityManagerService)
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        data.writeString(profileFile);
        if (profileFd != null) {
            data.writeInt(1);
            profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }
时间: 2024-10-02 07:28:19

android activity 启动过程分析(source code 4.4)的相关文章

Android Activity启动模式

在Android的联机文档中,有对Activity的简单介绍,现在通过编写代码对Activity的启动模式做一个深入的理解.在配置文件AndroidManifest.xml中,activity元素的android:launchMode属性用来配置对应Activity的启动模式,目前有以下四种启动模式:1.standard2.singleTop3.singleTask4.singleInstance如果不对Activity设置启动模式,默认就是standard模式 一.standard 请看以下代

Android Branch and master source code merge(patch)

Environment : Android 4.4.2 merge with Android 4.4.3(with other vendors source code) 1.确定你要merge 到 其他分支的版本,并在服务器测获得具体lable 对应的commit 或者 从build 对应的Repo Manifest 中找到要patch 到目标代码的Commit ID <?xml version="1.0" encoding="UTF-8"?> <

Android Activity启动过程源码解析

背景 启动App内部的Activity,Android 6.0 系统概要 系统会为每个App创建一个进程,系统进程和App进程之间通过Binder通信    2个Binder接口 IActivityManager 和 IApplicationThread    几个Binder相关的类    ActivityManagerService extends ActivityManagerNative    ActivityManagerNative extends Binder implements

【Android】应用程序Activity启动过程分析

在Android系统中,有两种操作会引发Activity的启动,一种用户点击应用程序图标时,Launcher会为我们启动应用程序的主Activity:应用程序的默认Activity启动起来后,它又可以在内部通过调用startActvity接口启动新的Activity,依此类推,每一个Activity都可以在内部启动新的Activity.通过这种连锁反应,按需启动Activity,从而完成应用程序的功能. Activity的启动方式有两种,一种是显式的,一种是隐式的,隐式启动可以使得Activit

Activity启动过程分析

Android的四大组件中除了BroadCastReceiver以外,其他三种组件都必须在AndroidManifest中注册,对于BroadCastReceiver来说,它既可以在AndroidManifest中注册也可以通过代码来注册,在调用方式上,Activity.Service和BroadCastReceiver需要借助Intent,而ContentProvider则无需借助Intent. Activity是一种展示型组件,用于向用户直接展示一个界面,并且可以接收用户的输入信息从而进行交

android activity启动的4种方式记录及打开其他应用的activity的坑

Android启动的四种方式分别为standard,singleTop,singleTask,singleInstence. standard是最常见的activity启动方式,也是默认的启动的方式.当启动一个activity的时候他将进入返回栈的栈顶.系统不会管栈内是否有相同的activity,方式像后入先出. singleTop方式是在活动启动的时候,系统先判定栈顶是否有相同的活动,如果没有则新建活动,否则将不新建活动.而是直接使用他. singleTask方式在活动启动的时候,系统先判定栈

Android Activity启动模式的功能验证

之前一直都是看别人写的启动模式,发现网上大多数的内容都是抄袭来抄袭去,直到最近看了开发艺术这本书,发现之前对启动模式的理解过于简单,很多东西都没有考虑到,为了加深理解,于是决定自己动手去验证一下四个启动模式.当然我们也从最简单的启动模式开始验证. 为了打印方便,定义一个基础Activity,在其onCreate方法和onNewIntent方法中打印出当前Activity的日志信息,主要包括所属的task,当前类的hashcode,以及taskAffinity的值.之后我们进行测试的Activit

AndroidのActivity启动模式

Activity启动模式      .概念    Activity启动模式定义了Activity启动的规则,它决定着Activity的实例创建与重用与否    .属性   Activity的启动模式在menifest.xml中的<activity>标签中设置,属性为launchMode    .分类     Activity的启动模式分为四类: standard . singleTop . singleTask . singleInstance     .备注   Android采用Task来

Android开机启动过程分析

首先android是基于Linux的内核,只有先加载了kernel才能启动安卓,对于Linux来说android只是其上的一个应用程序.Android的启动大致可以形象的划分为三个过程: Init->init.rc->zygote.从事嵌入式开发的人都知道,Linux加载完内核驱动后会挂载'/'根文件系统,挂载完成后会执行'/init'二进制程序,这也是内核启动后执行的第一个用户程序,android里面也是这样.这个程序的main函数位于android/system/core/init/ini