Android是基于Linux内核的,当手机启动,加载完Linux内核后,会由Linux系统的init祖先进程fork出Zygote进程,所有的Android应用程序进程以及系统服务进程都是这个Zygote的子进程(由它fork出来的)。其中最重要的一个就是SystemServer,在ZygoteInit类的main方法中,会调用startSystemServer方法开启系统里面重要的服务,包括ActivityManagerService(Activity管理器,简称AMS,可以理解为一个服务进程,负责Activity的生命周期管理)、PackageManagerService(包管理器)、WindowManagerService(窗口管理器)、PowerManagerService(电量管理器)等等,这个过程中还会创建系统上下文。
public final class SystemServer {
//zygote的主入口
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
...ignore some code...
//加载本地系统服务库,并进行初始化
System.loadLibrary("android_servers");
nativeInit();
// 创建系统上下文
createSystemContext();
//初始化SystemServiceManager对象,下面的系统服务开启都需要调用SystemServiceManager.startService(Class),这个方法通过反射来启动对应的服务
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//开启服务
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
...ignore some code...
}
//初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
//在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。
private void startBootstrapServices() {
...ignore some code...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 现在电源管理已经开启,ActivityManagerService负责电源管理功能
mActivityManagerService.initPowerManagement();
// 初始化DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//初始化PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...ignore some code...
}
}
注意一个很重要的地方
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
这里干了三件事,一个是创建ActivityThread,这个ActivityThread就是我们常说的“主线程”,也就是所谓的UI线程,APP的主入口。ActivityThread随后会创建一个mainLooper来开启消息循环,这也就是为什么在"主线程"中我们使用Handler不需要手动创建Looper的原因。第二件事是获得了系统的上下文,第三件事是设置了默认的主题。如果想要启动新的应用,ActivityManagerService会通过socket进程间通信(IPC)机制来通知Zygote进程fork出新的进程。
系统第一个启动的APP是Lancher,也就是我们手机的主界面,继承自Activity,实现了点击事件、触摸、长按等接口,在android源码Lancher.java中,我们可以看到onclick方法
public void onClick(View v) {
...ignore some code...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
//开始开启Activity
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
//如果点击的是图标文件夹,就打开文件夹
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {
...ignore some code...
}
}
可以看出我们点击了主界面上的应用图标后调用的就是startActivitySafely这个方法,继续深入进去,然后再往下走,我们发现调用的是startActivity方法,最后会调用Instrumentation.execStartActivity(),Instrumentation这个类就是完成对Application和Activity初始化和生命周期的工具类,然后Instrumentation会通过ActivityManagerService的远程接口向AMS发消息,让他启动一个Activity。 也就是说调用startActivity(Intent)以后, 会通过Binder IPC机制, 最终调用到ActivityManagerService。AMS会通过socket通道传递参数给Zygote进程。Zygote孵化自身, 并调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid。ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环。在ActivityThread会创建并绑定Application,这个时候才会realStartActivity(),并且AMS会将生成的Activity加到ActivityTask的栈顶,并通知ActivityThread暂停当前Activity(暂停Lancher,进入我们自己的APP)。
mgr.attachApplication(mAppThread)
这个就会通过Binder调用到AMS里面对应的方法,继续研究源码,在handleBindApplication中,完成了Application的创建public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) { }
mActivityThread.mAllApplications.add(app);
mApplication = app;
//传进来的是null,所以这里不会执行,onCreate在上一层执行
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
}
}
...ignore some code...
}
return app;
}
上面的三点,用一张图来改概括,就是
public void reportFullyDrawnLocked() {
final long curTime = SystemClock.uptimeMillis();
if (displayStartTime != 0) {
reportLaunchTimeLocked(curTime);
}
final ActivityStack stack = task.stack;
if (fullyDrawnStartTime != 0 && stack != null) {
final long thisTime = curTime - fullyDrawnStartTime;
final long totalTime = stack.mFullyDrawnStartTime != 0
? (curTime - stack.mFullyDrawnStartTime) : thisTime;
}
逻辑如下图
把这个样式设置给启动的Activity
然后在Activity的onCreate方法,把Activity设置回原来的主题
@Override
protected void onCreate(Bundle savedInstanceState) {
//替换为原来的主题,在onCreate之前调用
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
}
这样在启动时就通过给用户看一张图片或是广告来防止黑白屏的尴尬。
new Thread(){
@Override
public void run() {
initNim();
initImagePicker();
initOkHttp();
}
}.start();
File file = new File(Environment.getExternalStorageDirectory(), "app7");
Log.i(TAG, "onCreate: " + file.getAbsolutePath());
Debug.startMethodTracing(file.getAbsolutePath());
//对全局属性赋值
mContext = getApplicationContext();
mMainThread = Thread.currentThread();
mMainThreadId = android.os.Process.myTid();
mMainLooper = getMainLooper();
mHandler = new Handler();
initNim();
initImagePicker();
initOkHttp();
Debug.stopMethodTracing();
如果你用的是模拟器,就可以使用下面的控制台命令将trace文件拉出到桌面上
cd Desktop
adb pull /storage/sdcard/app7.trace
然后将这个trace文件拖入android studio 就可以了,可以看到这样的界面