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

简介:

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

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

        MainActivity的启动过程如下图所示: 

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

        Step 1. Launcher.startActivitySafely

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

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


  
  
  1. /**  
  2. * Default launcher application.  
  3. */   
  4. public final class Launcher extends Activity   
  5.         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {   
  6.    
  7.     ......   
  8.    
  9.     /**  
  10.     * Launches the intent referred by the clicked shortcut.  
  11.     *  
  12.     * @param v The view representing the clicked shortcut.  
  13.     */   
  14.     public void onClick(View v) {   
  15.         Object tag = v.getTag();   
  16.         if (tag instanceof ShortcutInfo) {   
  17.             // Open shortcut   
  18.             final Intent intent = ((ShortcutInfo) tag).intent;   
  19.             int[] pos = new int[2];   
  20.             v.getLocationOnScreen(pos);   
  21.             intent.setSourceBounds(new Rect(pos[0], pos[1],   
  22.                 pos[0] + v.getWidth(), pos[1] + v.getHeight()));   
  23.             startActivitySafely(intent, tag);   
  24.         } else if (tag instanceof FolderInfo) {   
  25.             ......   
  26.         } else if (v == mHandleView) {   
  27.             ......   
  28.         }   
  29.     }   
  30.    
  31.     void startActivitySafely(Intent intent, Object tag) {   
  32.         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   
  33.         try {   
  34.             startActivity(intent);   
  35.         } catch (ActivityNotFoundException e) {   
  36.             ......   
  37.         } catch (SecurityException e) {   
  38.             ......   
  39.         }   
  40.     }   
  41.    
  42.     ......   
  43.    
  44. }   

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


  
  
  1. <activity android:name=".MainActivity"     
  2.       android:label="@string/app_name">     
  3.        <intent-filter>     
  4.         <action android:name="android.intent.action.MAIN" />     
  5.         <category android:name="android.intent.category.LAUNCHER" />     
  6.     </intent-filter>     
  7. </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是一个非常复杂的概念,有兴趣的读者可以到官网http://developer.android.com/guide/topics/manifest/activity-element.html查看相关的资料。这里,我们只要知道,这个MainActivity要在一个新的Task中启动就可以了。

        Step 2. Activity.startActivity

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


  
  
  1. public class Activity extends ContextThemeWrapper   
  2.         implements LayoutInflater.Factory,   
  3.         Window.Callback, KeyEvent.Callback,   
  4.         OnCreateContextMenuListener, ComponentCallbacks {   
  5.    
  6.     ......   
  7.    
  8.     @Override   
  9.     public void startActivity(Intent intent) {   
  10.         startActivityForResult(intent, -1);   
  11.     }   
  12.    
  13.     ......   
  14.    
  15. }   

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

        Step 3. Activity.startActivityForResult

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


  
  
  1. public class Activity extends ContextThemeWrapper   
  2.         implements LayoutInflater.Factory,   
  3.         Window.Callback, KeyEvent.Callback,   
  4.         OnCreateContextMenuListener, ComponentCallbacks {   
  5.    
  6.     ......   
  7.    
  8.     public void startActivityForResult(Intent intent, int requestCode) {   
  9.         if (mParent == null) {   
  10.             Instrumentation.ActivityResult ar =   
  11.                 mInstrumentation.execStartActivity(   
  12.                 this, mMainThread.getApplicationThread(), mToken, this,   
  13.                 intent, requestCode);   
  14.             ......   
  15.         } else {   
  16.             ......   
  17.         }   
  18.    
  19.    
  20.     ......   
  21.    
  22. }   

         这里的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文件中:


  
  
  1. public class Instrumentation {   
  2.    
  3.     ......   
  4.    
  5.     public ActivityResult execStartActivity(   
  6.     Context who, IBinder contextThread, IBinder token, Activity target,   
  7.     Intent intent, int requestCode) {   
  8.         IApplicationThread whoThread = (IApplicationThread) contextThread;   
  9.         if (mActivityMonitors != null) {   
  10.             ......   
  11.         }   
  12.         try {   
  13.             int result = ActivityManagerNative.getDefault()   
  14.                 .startActivity(whoThread, intent,   
  15.                 intent.resolveTypeIfNeeded(who.getContentResolver()),   
  16.                 null0, token, target != null ? target.mEmbeddedID : null,   
  17.                 requestCode, falsefalse);   
  18.             ......   
  19.         } catch (RemoteException e) {   
  20.         }   
  21.         return null;   
  22.     }   
  23.    
  24.     ......   
  25.    
  26. }   

         这里的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文件中:


  
  
  1. class ActivityManagerProxy implements IActivityManager   
  2. {   
  3.    
  4.     ......   
  5.    
  6.     public int startActivity(IApplicationThread caller, Intent intent,   
  7.             String resolvedType, Uri[] grantedUriPermissions, int grantedMode,   
  8.             IBinder resultTo, String resultWho,   
  9.             int requestCode, boolean onlyIfNeeded,   
  10.             boolean debug) throws RemoteException {   
  11.         Parcel data = Parcel.obtain();   
  12.         Parcel reply = Parcel.obtain();   
  13.         data.writeInterfaceToken(IActivityManager.descriptor);   
  14.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);   
  15.         intent.writeToParcel(data, 0);   
  16.         data.writeString(resolvedType);   
  17.         data.writeTypedArray(grantedUriPermissions, 0);   
  18.         data.writeInt(grantedMode);   
  19.         data.writeStrongBinder(resultTo);   
  20.         data.writeString(resultWho);   
  21.         data.writeInt(requestCode);   
  22.         data.writeInt(onlyIfNeeded ? 1 : 0);   
  23.         data.writeInt(debug ? 1 : 0);   
  24.         mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);   
  25.         reply.readException();   
  26.         int result = reply.readInt();   
  27.         reply.recycle();   
  28.         data.recycle();   
  29.         return result;   
  30.     }   
  31.    
  32.     ......   
  33.    
  34. }   

        这里的参数比较多,我们先整理一下。从上面的调用可以知道,这里的参数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文件中:


  
  
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.    
  4.     ......   
  5.    
  6.     public final int startActivity(IApplicationThread caller,   
  7.             Intent intent, String resolvedType, Uri[] grantedUriPermissions,   
  8.             int grantedMode, IBinder resultTo,   
  9.             String resultWho, int requestCode, boolean onlyIfNeeded,   
  10.             boolean debug) {   
  11.         return mMainStack.startActivityMayWait(caller, intent, resolvedType,   
  12.             grantedUriPermissions, grantedMode, resultTo, resultWho,   
  13.             requestCode, onlyIfNeeded, debug, nullnull);   
  14.     }   
  15.    
  16.    
  17.     ......   
  18.    
  19. }   

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

        Step 7. ActivityStack.startActivityMayWait

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


  
  
  1. public class ActivityStack {   
  2.    
  3.     ......   
  4.    
  5.     final int startActivityMayWait(IApplicationThread caller,   
  6.             Intent intent, String resolvedType, Uri[] grantedUriPermissions,   
  7.             int grantedMode, IBinder resultTo,   
  8.             String resultWho, int requestCode, boolean onlyIfNeeded,   
  9.             boolean debug, WaitResult outResult, Configuration config) {   
  10.    
  11.         ......   
  12.    
  13.         boolean componentSpecified = intent.getComponent() != null;   
  14.    
  15.         // Don't modify the client's object!   
  16.         intent = new Intent(intent);   
  17.    
  18.         // Collect information about the target of the Intent.   
  19.         ActivityInfo aInfo;   
  20.         try {   
  21.             ResolveInfo rInfo =   
  22.                 AppGlobals.getPackageManager().resolveIntent(   
  23.                 intent, resolvedType,   
  24.                 PackageManager.MATCH_DEFAULT_ONLY   
  25.                 | ActivityManagerService.STOCK_PM_FLAGS);   
  26.             aInfo = rInfo != null ? rInfo.activityInfo : null;   
  27.         } catch (RemoteException e) {   
  28.             ......   
  29.         }   
  30.    
  31.         if (aInfo != null) {   
  32.             // Store the found target back into the intent, because now that   
  33.             // we have it we never want to do this again.  For example, if the   
  34.             // user navigates back to this point in the history, we should   
  35.             // always restart the exact same activity.   
  36.             intent.setComponent(new ComponentName(   
  37.                 aInfo.applicationInfo.packageName, aInfo.name));   
  38.             ......   
  39.         }   
  40.    
  41.         synchronized (mService) {   
  42.             int callingPid;   
  43.             int callingUid;   
  44.             if (caller == null) {   
  45.                 ......   
  46.             } else {   
  47.                 callingPid = callingUid = -1;   
  48.             }   
  49.    
  50.             mConfigWillChange = config != null   
  51.                 && mService.mConfiguration.diff(config) != 0;   
  52.    
  53.             ......   
  54.    
  55.             if (mMainStack && aInfo != null &&   
  56.                 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {   
  57.                      
  58.                       ......   
  59.    
  60.             }   
  61.    
  62.             int res = startActivityLocked(caller, intent, resolvedType,   
  63.                 grantedUriPermissions, grantedMode, aInfo,   
  64.                 resultTo, resultWho, requestCode, callingPid, callingUid,   
  65.                 onlyIfNeeded, componentSpecified);   
  66.    
  67.             if (mConfigWillChange && mMainStack) {   
  68.                 ......   
  69.             }   
  70.    
  71.             ......   
  72.    
  73.             if (outResult != null) {   
  74.                 ......   
  75.             }   
  76.    
  77.             return res;   
  78.         }   
  79.    
  80.     }   
  81.    
  82.     ......   
  83.    
  84. }   

 

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

 

        下面语句对参数intent的内容进行解析,得到MainActivity的相关信息,保存在aInfo变量中:


  
  
  1.    ActivityInfo aInfo;   
  2.    try {   
  3. ResolveInfo rInfo =   
  4. AppGlobals.getPackageManager().resolveIntent(   
  5.     intent, resolvedType,   
  6.     PackageManager.MATCH_DEFAULT_ONLY   
  7.     | ActivityManagerService.STOCK_PM_FLAGS);   
  8. aInfo = rInfo != null ? rInfo.activityInfo : null;   
  9.    } catch (RemoteException e) {   
  10.     ......   
  11.    }   

        解析之后,得到的aInfo.applicationInfo.packageName的值为"shy.luo.activity",aInfo.name的值为"shy.luo.activity.MainActivity",这是在这个实例的配置文件AndroidManifest.xml里面配置的。

        此外,函数开始的地方调用intent.getComponent()函数的返回值不为null,因此,这里的componentSpecified变量为true。

        接下去就调用startActivityLocked进一步处理了。





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/965994,如需转载请自行联系原作者

目录
相关文章
|
12天前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
20天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
45 15
Android 系统缓存扫描与清理方法分析
|
12天前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
12天前
|
存储 搜索推荐 Java
打造个性化安卓应用:从设计到实现
【10月更文挑战第30天】在数字化时代,拥有一个个性化的安卓应用不仅能够提升用户体验,还能加强品牌识别度。本文将引导您了解如何从零开始设计和实现一个安卓应用,涵盖用户界面设计、功能开发和性能优化等关键环节。我们将以一个简单的记事本应用为例,展示如何通过Android Studio工具和Java语言实现基本功能,同时确保应用流畅运行。无论您是初学者还是希望提升现有技能的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧。
|
16天前
|
搜索推荐 开发工具 Android开发
打造个性化Android应用:从设计到实现的旅程
【10月更文挑战第26天】在这个数字时代,拥有一个能够脱颖而出的移动应用是成功的关键。本文将引导您了解如何从概念化阶段出发,通过设计、开发直至发布,一步步构建一个既美观又实用的Android应用。我们将探讨用户体验(UX)设计的重要性,介绍Android开发的核心组件,并通过实际案例展示如何克服开发中的挑战。无论您是初学者还是有经验的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧,帮助您在竞争激烈的应用市场中脱颖而出。
|
18天前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
28 2
|
21天前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
46 5
|
21天前
|
移动开发 Dart 搜索推荐
打造个性化安卓应用:从零开始的Flutter之旅
【10月更文挑战第20天】本文将引导你开启Flutter开发之旅,通过简单易懂的语言和步骤,让你了解如何从零开始构建一个安卓应用。我们将一起探索Flutter的魅力,实现快速开发,并见证代码示例如何生动地转化为用户界面。无论你是编程新手还是希望扩展技能的开发者,这篇文章都将为你提供价值。
|
1月前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
43 4
|
3天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。