码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2015-08-30 00:44:10      阅读:346      评论:0      收藏:0      [点我收藏+]

标签:

    说实话,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; }

 

 

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

标签:

原文地址:http://www.cnblogs.com/kernel-style/p/4770071.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!