Android程序启动过程源码分析.docx
《Android程序启动过程源码分析.docx》由会员分享,可在线阅读,更多相关《Android程序启动过程源码分析.docx(71页珍藏版)》请在冰豆网上搜索。
Android程序启动过程源码分析
Android应用程序启动过程源代码分析
分类:
Android2011-08-1900:
585447人阅读评论(40)收藏举报
前文简要介绍了Android应用程序的Activity的启动过程。
在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程,本文将详细分析应用程序框架层的源代码,了解Android应用程序的启动过程。
在上一篇文章Android应用程序的Activity启动过程简要介绍和学习计划中,我们举例子说明了启动Android应用程序中的Activity的两种情景,其中,在手机屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来。
这种启动方式的特点是会启动一个新的进程来加载相应的Activity。
这里,我们继续以这个例子为例来说明Android应用程序的启动过程,即MainActivity的启动过程。
MainActivity的启动过程如下图所示:
点击查看大图
下面详细分析每一步是如何实现的。
Step1.Launcher.startActivitySafely
在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。
Launcher的源代码工程在packages/apps/Launcher2目录下,负责启动其它应用程序的源代码实现在src/com/android/launcher2/Launcher.java文件中:
viewplaincopytoclipboardprint?
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文件中配置的:
viewplaincopytoclipboardprint?
1.name=".MainActivity"
2. android:
label="@string/app_name">
3.
4. name="android.intent.action.MAIN" />
5. name="android.intent.category.LAUNCHER" />
6.
7.
因此,这里的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是一个非常复杂的概念,有兴趣的读者可以到官网
Step2.Activity.startActivity
在Step1中,我们看到,Launcher继承于Activity类,而Activity类实现了startActivity函数,因此,这里就调用了Activity.startActivity函数,它实现在frameworks/base/core/java/android/app/Activity.java文件中:
viewplaincopytoclipboardprint?
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结束后的返回结果。
Step3. Activity.startActivityForResult
这个函数也是实现在frameworks/base/core/java/android/app/Activity.java文件中:
viewplaincopytoclipboardprint?
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对象的远程接口。
Step4.Instrumentation.execStartActivity
这个函数定义在frameworks/base/core/java/android/app/Instrumentation.java文件中:
viewplaincopytoclipboardprint?
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. null, 0, token, target !
= null ?
target.mEmbeddedID :
null,
17. requestCode, false, false);
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,我们不用关注。
Step5.ActivityManagerProxy.startActivity
这个函数定义在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:
viewplaincopytoclipboardprint?
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。
Step6.ActivityManagerService.startActivity
上一步Step5通过Binder驱动程序就进入到ActivityManagerService的startActivity函数来了,它定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
viewplaincopytoclipboardprint?
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, null, null);
14. }
15.
16.
17. ......
18.
19.}
这里只是简单地将操作转发给成员变量mMainStack的startActivityMayWait函数,这里的mMainStack的类型为ActivityStack。