我们在写C、C++或java应用时,都会有一个main函数,但Android的main函数在哪里呢?偶记得从第一个HelloWorld应用开始,就知道,只要在AndroidManifest配置表中对Activity的intent-filter进行配置,action为android.intent.action.MAIN,category为android.intent.category.LAUNCHER,应用程序启动的时候就会首先启动这个Activity,此Activity也就是应用的入口;后来又知道Application这个类,只要有类继承Application,并在AndroidManifest配置表中对application的name进行配置该类,android应用启动后会把该类的attachBaseContext和onCreate方法作为程序开发入口。实际上是不是这样的呢?本篇博文将会从源码角度来分析。
在说Android应用程序开发入口之前,我们有必要了解一下android系统的启动和Android应用程序的启动流程,这样有助于我们对Android系统有一个整体的认识。首先,让我们来简单了解一下Android系统的启动流程。
一、Android系统的启动
Android系统的启动流程是怎样的呢?首先先来看一下流程图:
根据图,我们知Android启动流程的步骤如下:
1.启动电源
当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。2.引导程序BootLoader执行
引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。3.Linux内核启动
内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。4.init进程启动
初始化和启动属性服务,并且启动Zygote进程。5.Zygote进程启动
创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动SystemServer进程。6.SystemServer进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务,例如:ActivityManagerService、PowerManagerService、PackageManagerService,BatteryService、UsageStatsService等其他80多个系统服务。7.Launcher启动
被SystemServer进程启动的ActivityManagerService会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
关于Android系统的启动源码分析,这里推荐大神刘望舒的几篇文章,讲得比较详细:
Android系统启动流程(二)解析Zygote进程启动过程
Android系统启动流程(三)解析SyetemServer进程启动过程
Android系统启动流程(四)Launcher启动过程与系统启动流程
二、Android应用程序启动
上面说到,当Android系统启动完成之后,Lancher也就启动完成了,在我们的桌面上就会看到已安装的应用快捷图标。点击快捷图标,就能启动我们的应用程序。我们知道,android系统中的每一个应用程序,都是独立运行在自己的进程中的,所以在点击应用快捷图标后,如果应用程序还没有进程,首先应该会先建立应用程序的进程。具体流程是怎样的呢?我们先来看流程图:
从流程图知,应用程序在没有创建进程的情况下,会通过ActivitServiceManager去请求服务端Socket,服务端Socket再去请求Zygote进程,让其帮忙建立进程,而Zygote进程会fork自身来创建应用程序进程。应用程序进程创建的同时,应用程序的主线程也会创建,与主线程息息相关的ActivityThread类也会创建,并调用自身的main方法,进行相关的初始化。
具体进程是怎么创建的,这里也还是推荐大神刘望舒的两篇文章,其中非常详细的分析了应用进程的创建过程,想了解的可以看一下。
好了,下面我们来继续说说ActivityThread的main方法,也即Android应用程序的入口。
三、Android应用程序入口源码分析
通过Android应用程序的启动,我们知道android应用程序的入口,即ActivityThread的main方法。但在我们开发的时候,很少接触ActivityThread类,主要还是Application和Activity,他俩与ActivityThread的关系怎样呢?让我们从源码中来看看,ActivityThread的main方法:
在main方法中,主线程的Looper实现了初始化和消息循环,这与Android的消息机制息息相关。关于消息机制,我已写过一个篇文章为Android消息机制源码解析(Handler),想了解的可以看一下。这里我们主要来看一下ActivityThread的初始化和attach方法,其中ActivityThread初始化构造方法什么也没做,没啥好看的,我们主要来看看attach方法
ActivityThread调用attach()传入的参数是false,不是system。注释1通过静态方法ActivityManagerNative.getDefault()获取IActivityManager,实际上是获取到ActivityManagerProxy类,让我们来看ActivityManagerNative.getDefault()方法,进入ActivityManagerNative类
通过查看ActivityManagerProxy类,了解到它实现IActivityManager接口,mgr就是ActivityManagerProxy。知道返回的类后,我们再来看一下注释2,mgr.attachApplication(mAppThread),其中mAppThread为ApplicationThread,让我们再进入ActivityManagerProxy,看看attachApplication方法
从源码中,了解到mRemote是一个IBinder,通过Binder实现进程间通信(Android核心进程通信方法),从而调用到ActivityServiceManager里面对应的方法
我们来继续看方法attachApplicationLocked()
在attachApplicationLocked()方法中,细节比较多,我们省略掉了,主要来看一下核心方法bindApplication(),其中thread就是ActivityThread中ApplicationThread类,让我们再来看ApplicationThread中的bindApplication()方法
其中queueOrSendMessage方法主要就是向Handler发送了一个Message,让我们来看看具体的方法
容易知道,主要就是向Handler mH中发送一条消息,根据Handler消息循环机制,可以在handMessage查看处理方法,根据H.BIND_APPLICATION
继续看handleBindApplication()方法
通过分析知data为AppBindData,data.info是一个LoadeApk对象。data.info.makeApplication(),让我们继续看LoadeApk中的方法
主要还是调ActivityThread中mInstrumentation.newApplication()方法,并传入了继承Application的类的类名appClass,当Applicaiton建立后,马上就调用了方法2即Application的onCreate(),让我们先来看Instrumentation中的newApplication()方法
到这里,就建立了应用程序的Application,然而在Application中那个方法是最先调用的呢?让我们继续看一下
由此我们知道Application初始化后,首先调用的是attachBaseContext()方法,其次才是Application的onCreate方法,让我们看一下调用onCreate()方法,在前面的makeApplication()方法中,有此代码instrumentation.callApplicationOnCreate(app),我们继续来看看源码
到这里Android应用程序的入口源码就分析完了。
注:源码采用android-4.1.1_r1版本,建议下载源码然后自己走一遍流程,这样更能加深理解。
四、总结
Android应用程序的入口是ActivityThread的main方法,而Android应用程序的开发入口是Application的attachBaseContext()和onCreate()。如果有类继承Application,并在Androidmanifest中配置了,它就会优先启动。在继承Application类初始化后,首先调用的是attachBaseContext()方法,其次才是onCreate方法。
五、相关及参考文档
Android系统启动流程(二)解析Zygote进程启动过程
Android系统启动流程(三)解析SyetemServer进程启动过程