App启动流程 包括 bootloader , Kernel , init,zygote和system_server.不过bootloader , Kernel 已经偏操作系统内核和驱动方面了,不做细讲,这里从init开始带大家深入理解App启动流程和顺序.
App
bootloader
Kernel
init
zygote
system_server
init是Linux用户的第一个进程,进程号是1,说这个主要目的是引入我们话匣子zygote,init是如何创建zygote以及init属性服务是如何工作的呢? 代码很复杂,我也看不懂,你只要知道是通过init.rc解析,然后执行各个阶段的动作,最后创建zygote就行了,当然还要处理socket属性服务方面的事情,因为涉及很多和Linux系统相关的知识.作为应用开发就没必要太关注这个了.
1
init.rc
socket
Linux
当我上面没说,直接跳到zygote,zygote中文意思是受精卵,他是Android系统牵动Java世界的纽带.而system_server人如其名,系统中重要的server都会驻留在Java中. zygote和system_server这两个进程分别是Java世界的半边天,任何进程的死亡,都会导致Java世界的Crash. zygote最初名字是android_process,这个名字是Android.mk文件被指定的,它本身就是个Native程序,和内核和驱动均无关. 我们不需要深究太多,只要了解一点,Zygote觉的自己工作压力太大,于是通过startSystemServer分裂system_server作为Java的世界服务.zygote被命名为受精卵一点都不过分,如果支持中文编码其实更适合盘古_女娲
受精卵
Android
Java
server
Crash
android_process
Android.mk
Native
Zygote
startSystemServer
盘古_女娲
ZygoteInt 调用 startSystemServer 创建 system_server,system_server 通过 hsp 方法完成自己的使命,并抛出异常,最终调用SystemServer 引入 main 方法,main 方法加载 libandroid_server.so 并调用 native 的init1函数,init1函数通过JNI调用init2函数,init2函数创建一个线程,用于加载各种service,init1函数最终加入Binder通信系统
ZygoteInt
hsp
SystemServer
main
libandroid_server.so
native
init1
JNI
init2
service
Binder
1. 深入理解 Android 2. App系统启动流程分析 3. App 启动过程(含 Activity 启动过程) | 安卓 offer 收割基
App的启动方式: 冷启动:当启动应用时,后台没有该应用的进程。这是系统会创建一个新的进程分配给该应用。这是app的冷启动。冷启动因为系统会分配一个新的进程给app,此时的app会创建Applocation,然后才回去创建MainActivity,最后显示在界面上。
热启动:当启动应用的时候,后台已经存在该应用的进程了,(列:按back和home应用虽然会退出但是应用的进程仍然在后台运行,可以进入任务列表查看)这个是热启动,因为热启动不会创建进程。所以app不会创建Applocation,只会初始化MainActivity。一个应用从创建到销毁只会执行一次Applocation。
应用的启动步骤:
(1) Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity
(2) ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态
(3) Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行
(4) ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信
(5) ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了
应用启动流程涉及到的类和对象:
(1) Launcher:Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity,实现了点击、长按等回调接口,来接收用户的输入。
(2) ActivityManagerServices:简称AMS,服务端对象,负责系统中所有Activity的生命周期。
(3) ActivityThread:App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作
(4) ApplicationThread:用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。
(5) ApplicationThreadProxy:是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。
(6) Instrumentation:每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。
(7) ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
(8) ActivityRecord:ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
(9) TaskRecord:AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。
App启动白屏或黑屏的原因:是因为已进入到Activity,但是未加载到布局文件,就先显示来windows窗口的背景。黑屏/白屏就是显示的windows背景(这个就是theme的设置)
App启动白屏或黑屏解决方案:
(1) 为Theme设置背景图(会给人一种快速加载的感觉)
<stylename="Theme.AppStartLoad"parent="android:Theme">
<itemname="android:windowBackground">@drawable/ipod_bg
<itemname="android:windowNoTitle">true
(2) 为Theme设置透明属性(会给人较慢加载出来感觉)
<stylename="Theme.AppStartLoadTranslucent"parent="android:Theme">
<itemname="android:windowIsTranslucent">true
App的启动优化:
(1) Application的创建过程中尽量少的进行耗时操作
(2) 如果用到SharePreference,尽量在异步线程中操作
(3) 减少布局的层次,并且生命周期回调的方法中尽量减少耗时的操作
APP启动在项目中碰到过黑白屏的问题
为什么我的 APP 启动会白屏或者黑屏
有时候我们会发现,我们在启动我们自己的 APP 的时候,总是有那么点时间是白屏(黑屏),经过了白屏(黑屏)后才会进入我们的 APP。那么这是为什么呢?
有很多的初始化放到了 Application 中去完成了,那么这个时候刚打开程序的时候就会有个耗时,就会出现白屏的效果。
所以这里程序加载有个顺序,当打开一个 Activity 的时候,并且这个 Activity 所属的 Application 还没有运行,系统会首先为这个 Activity 创建一个进程,创建进程的时候就会调用 Application 的 onCreate 方法。进程的创建和 onCreate 内部的初始化是需要时间的,如果这个时候过长,没有任何反应的话,那么对于用户来说是不不知道的,用户还以为自己没有点到呢,所以很显然是不可能在原页面等待加载的,那么这个时候就有了 StartingWindow(PerviewWindow)的出现,StartingWindow 出现在应用程序进程创建并且初始化完成之前,是个临时的窗口,对应的 WindowType是 TYPE_APPLICATION_STARTING 作用就是告诉用户,系统已经收到我们的操作了,正在对程序进行初始化,只要初始化完毕后就会移除这个窗口。
所以其实我们看到的白屏或者黑屏就是 StartingWindow,那么为什么是白色或者黑色呢?我们一般都会给我们的 Application 和 Activity 设置 Theme,系统就会根据我们所设置的 Theme 来决定 StartingWindow 的颜色。我们都知道 Window 布局的顶层是 DecorView,而 StaringWindow 显示的是一个空的 DecorView,只是这个 DecorView 会应用我们的这个 Activity 所指定的 Theme。我们默认的 Theme 是 @android:style/Theme.Light 的话,这个时候就会产生白屏了。黑屏就是应用了 @android:style/Theme.Black,好了到这里我们就彻底明白为什么会出现白屏或者黑屏了。
app的启动流程分析:https://www.jianshu.com/p/28281b54d318
首先放上我参考的文章,感觉写的不错。Android - Activity 启动过程 我先说一下我理解的一个应用启动的大致流程。 第一步我们点击桌面上一个应用图标,这个时候管理者会向系统服务进程发送一个指令:我要打开一个activity;第二步既然要打开activity,总要有个新的进程装载吧,那么系统服务向最牛的进程,算是系统进程吧,发送创建A进程的请求,这个时候系统主进程会进行创建A进程的工作,先判断要创建的A进程是否存在,然后确定是否要创建A进程;第三步创建好A进程之后,A进程向系统服务进程说,我已经被创建好了,你可以给我发送我运行需要的东西了,然后系统服务进程就会向A进程发送指令,告诉A进程需要创建Application和activity等一系列操作。 上面一系列啰嗦的叙述,其中系统服务进程是system_server进程,最牛的系统主进程是Zygote进程,创建进程的操作是fock操作,判断进程的唯一性是查看ActivityManagerService中有没有A进程的ProcessRecord (可以理解为每个进程的uid+process)信息,创建A进程的同时在A进程中创建了ActivityThread;进程A中的ActivityThread向system_server进程的ActivityManagerService发送A进程创建好的指令,并把A进程中的ApplicationThread发给ActivityManagerService,然后system_server进程的ActivityManagerService通过ApplicationThreadProxy这个代理与进程中的ApplicationThread沟通,进一步在A进程中创建application和activity等
activity
A
Application
system_serve
fock
ActivityManagerService
ProcessRecord
uid+process
ActivityThread
ApplicationThread
ApplicationThreadProxy
application
这过程太复杂了,里边涉及了好多的点。只能大致的说一下,我再继续研究一下,有新的发现和想法再补充上来
public static void main(String[] args) { // 1. mainLooper Looper.prepareMainLooper(); // 2. 创建ActivityThread,执行attach ActivityThread thread = new ActivityThread(); thread.attach(false); // 3. Handler if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } // 4. loop() Looper.loop(); }
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
1、ActivityManagerService
简称 AMS,服务端对象,负责管理 Activity 生命周期。
2、ActivityThread
App 的入口,启动 App 后,会调用 ActivityThread.main(),开启 Looper、MessageQueue,与 ActivityManagerService 配合完成对 Activity 的管理。
3、ApplicationThread
实现 ActivityManagerService 与 ActivityThread 之间的交互,在 ActivityManagerService 需要管理 Application 中 Activity 的生命周期时,通过 ApplicationThread 代理对象和 ActivityThread 通信。
4、ApplicationThreadProxy
ApplicationThread 在服务端的代理对象,负责和客户端的 ApplicationThread 进行通信。
5、Instrumentation
每个应用程序只有一个 Instrumentation 对象,每个 Activity 内都有一个对该对象的引用,可以理解为应用进程的管家,ActivityThread 需要创建或者暂停某个 Activity 时,都需要通过 Instrumentation 进行操作。
6、ActivityStack
Activity 在 AMS 中的栈管理,用来记录已经启动的 Activity 的先后顺序、状态信息等,通过 ActivityStack 决定是否需要启动新的进程。
7、ActivityRecord
ActivityStack 管理的对象,每个 Activity 在 AMS 对应一个 ActivityRecord,用来记录 Activity 的状态以及其他管理信息,其实就是服务器端 Activity 对象的映射。
8、TaskRecord
AMS 抽象出来的一个任务的概念,是记录 ActivityRecord 的栈,一个 Task 包含若干个 ActivityRecord,AMS 通过 TaskRecord 确保 Activity 启动和退出的顺序。
在 Linux 中,所有的进程都是由 init 进程直接或间接 fork 出来的,Zygote 进程也不例外。
手机开机后,Linux 内核加载完成后,会启动一个 init 进程。
每一个 App 其实都是:
所以,在系统中的第一个 Zygote 进程启动之后,再打开一个 App,其实就是开启一个新的进程。而为了实现资源共用和更快的启动速度,Android 系统开启新进程的方式是:通过 fork 第一个 Zygote 进程开启新进程,换句话说,其他应用所在的进程都是 Zygote 的子进程。
SystemServer 是一个进程,也是由 Zygote 进程 fork 出来的。
系统里比较重要的服务都是从这个进程里开启的,比如 ActivityManagerService、WindowManagerService、PackageManagerService 等。
Zygote 开启的时候会调用 ZygoteInit.main()
public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); // 标记 Zygote 开启 ZygoteHooks.startZygoteNoThreadCreation(); // Zygote 进入它自己的进程组 try { Os.setpgid(0, 0); } catch (ErrnoException ex) { throw new RuntimeException("Failed to setpgid(0,0)", ex); } try { // 上报 Zygote 开启时间到分裂时间,除非重新启动 if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.elapsedRealtime()); } String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); bootTimingsTraceLog.traceBegin("ZygoteInit"); RuntimeInit.enableDdms(); // 开始 Zygote 初始化 SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } zygoteServer.registerServerSocket(socketName); // 在许多配置中, 避免急切的预加载资源和类文件 // 在许多事例中, 在第一次 fork 时会预加载一些优先级高的事情 if (!enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { Zygote.resetNicePriority(); } // 完成 Zygote 的初始化 SamplingProfilerIntegration.writeZygoteSnapshot(); // 做一个 GC 初始化,在启动之后进行清理 bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); gcAndFinalize(); bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC bootTimingsTraceLog.traceEnd(); // ZygoteInit // 禁止跟踪,以至于被 fork 的进程不能继承老的 Zygote Trace.setTracingEnabled(false); // Zygote 进程卸载根存储空间 Zygote.nativeUnmountStorageOnInit(); // 设置 seccomp 策略 Seccomp.setPolicy(); ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { startSystemServer(abiList, socketName, zygoteServer); } Log.i(TAG, "Accepting command socket connections"); zygoteServer.runSelectLoop(abiList); zygoteServer.closeServerSocket(); } catch (Zygote.MethodAndArgsCaller caller) { caller.run(); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); zygoteServer.closeServerSocket(); throw ex; } } // 为 fork SystemServer 进程准备参数 private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_IPC_LOCK, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_PTRACE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG, OsConstants.CAP_WAKE_ALARM ); // 没有容量的容器运行,避免设置它 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) { capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND); } // 硬编码开启 system server String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); // 请求 fork system server 进程 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); handleSystemServerProcess(parsedArgs); } return true; }
简称 AMS,服务端对象,负责系统中所有 Activity 生命周期。
初始化时机:SystemServer 进程开启时。
public static void main(String[] args) { new SystemServer().run(); } public SystemServer() { mFactoryTestMode = FactoryTest.getMode(); mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed")); } private void run() { try { traceBeginAndSlog("InitBeforeStartServices"); if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } String timezoneProperty = SystemProperties.get("persist.sys.timezone"); if (timezoneProperty == null || timezoneProperty.isEmpty()) { Slog.w(TAG, "Timezone not set; setting to GMT."); SystemProperties.set("persist.sys.timezone", "GMT"); } if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag(); SystemProperties.set("persist.sys.locale", languageTag); SystemProperties.set("persist.sys.language", ""); SystemProperties.set("persist.sys.country", ""); SystemProperties.set("persist.sys.localevar", ""); } // system server 不能多线程调用 Binder.setWarnOnBlocking(true); Slog.i(TAG, "Entered the Android system server!"); int uptimeMillis = (int) SystemClock.elapsedRealtime(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis); if (!mRuntimeRestart) { MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis); } SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } VMRuntime.getRuntime().clearGrowthLimit(); // system server 会一直运行,所以它需要高效使用其内存 VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); Build.ensureFingerprintProperty(); // 在 system server 中, 在没有显式指定用户的情况下,访问环境路径是会报错的 Environment.setUserRequired(true); // 在 system server 中, 应该对任何输入包进行解压缩,避免抛出 BadParcelableException BaseBundle.setShouldDefuse(true); // 确保 binder 进行系统调用时能运行在前台 BinderInternal.disableBackgroundScheduling(true); // 增加 system_server 中 binder 线程的数量 BinderInternal.setMaxThreads(sMaxBinderThreads); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // 初始化 native services(本地服务库) System.loadLibrary("android_servers"); // 检查上次我们尝试关闭是否失败 performPendingShutdown(); // 初始化 system context createSystemContext(); // 创建 system service manager mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // 准备 thread pool 并行初始化 tasks SystemServerInitThreadPool.get(); } finally { traceEnd(); // InitBeforeStartServices } // 开启服务 try { traceBeginAndSlog("StartServices"); startBootstrapServices(); startCoreServices(); startOtherServices(); SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { throw ex; } finally { traceEnd(); } if (!mRuntimeRestart && !isFirstBootOrUpgrade()) { int uptimeMillis = (int) SystemClock.elapsedRealtime(); MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis); final int MAX_UPTIME_MILLIS = 60 * 1000; if (uptimeMillis > MAX_UPTIME_MILLIS) { Slog.wtf(SYSTEM_SERVER_TIMING_TAG, "SystemServer init took too long. uptimeMillis=" + uptimeMillis); } } // 开启 Looper 循环 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } // 初始化上下文对象 mSystemContext private void createSystemContext() { // 创建 ActivityThread 对象,ActivityThread.systemMain() 会调用 ActivityThread.attach(),在 attach 中创建了 Application 对象,并调用了 Application.onCreate() ActivityThread activityThread = ActivityThread.systemMain(); // mSystemContext 实际上是一个 ContextImpl 对象 mSystemContext = activityThread.getSystemContext(); // 设置默认主题 mSystemContext.setTheme(DEFAULT_SYSTEM_THEME); final Context systemUiContext = activityThread.getSystemUiContext(); systemUiContext.setTheme(DEFAULT_SYSTEM_THEME); } private void startBootstrapServices() { ... // 初始化 ActivityManagerService mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); // Power manager 需要被提前创建因为其他服务需要它 mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); // 现在电源管理已经开始了,ActivityManagerService 负责电源管理功能 // 初始化电源管理 mActivityManagerService.initPowerManagement(); // 初始化 DisplayManagerService,在 package manager 之前 需要提供 Display manager mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); // 开启 PackageManagerService mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); ... }
这是系统进程开启时的流程,在这之后,会开启系统的 Launcher 程序,完成系统界面的加载与显示。
服务器端:所有 App 共用的系统服务,比如 ActivityManagerService、PackageManagerService、WindowManagerService 等,当某个 App 要进行某项操作时,要告诉这些系统服务。
客户端:某个 App。
App A 调用 startActivity 不能直接打开 App B 的某个页面,而是通过一系列调用,告诉 AMS 要打开 App B 的某个页面,AMS 会通知 Zygote 进程 fork 一个新进程,来开启 App B。
App 与 AMS 之间通过 Binder 进行 IPC 通信,AMS 与 Zygote 之间通过 Socket 进行通信。
AMS 的用途:
Launcher 本身也是一个应用程序。
每个 Activity 都持有 Instrumentation 对象的一个引用,但整个进程只会存在一个 Instrumentation 对象。
当 startActivityForResult() 调用之后,实际上还是调用了 mInstrumentation.execStartActivity()。
这个类里面的方法大多数和 Application 和 Activity 有关,这个类就是完成对 Application 和 Activity 初始化和生命周期的工具类。
AMS -> ActivityThread -> Instrumentation
startActivity() -> startActivityForResult() -> Instrumentation.execStartActivity() -> checkStartActivityResult() -> ActivityManager.getService().startActivity() -> ActivityManagerService.startActivity() -> startActivityAsUser() -> ActivityStarter.startActivityMayWait() -> startActivityLocked() -> startActivity() -> startActivityUnchecked() -> resumeTargetStackIfNeeded() -> ActivityStackSupervisor.resumeFocusedStackTopActivityLocked() -> ActivityStack.resumeTopActivityUncheckedLocked() -> resumeTopActivityInnerLocked() -> ActivityStackSupervisor.startSpecificActivityLocked() -> realStartActivityLocked() -> ActivityThread.ApplicationThread.scheduleLaunchActivity() -> sendMessage() -> handleLaunchActivity() -> performLaunchActivity() -> Instrumentation.callActivityOnCreate() -> Activity.performCreate() -> onCreate()
ActivityManager.getService() 返回的就是 ActivityManagerService 的远程接口。
客户端:ActivityManagerProxy -> Binder驱动 -> ActivityManagerService:服务器
如果 AMS 想要通知 ActivityThread 做一些事情,还是通过 Binder 通信,不过是换成了 ApplicationThread 和 ApplicationThreadProxy。
ApplicationThreadProxy:服务器 -> Binder 驱动 -> 客户端:ApplicationThread
ActivityThread.main()。
是在 ActivityThread 初始化的时候,就已经创建消息循环了,所以在主线程里面创建 Handler 不需要指定 Looper,而如果在其他线程使用 Handler,则需要单独使用 Looper.prepare() 和 Looper.loop() 创建消息循环。
也是在 ActivityThread.main() 的时候,再具体点,就是在 thread.attach(false) 的时候。
参考:APP启动过程
Activity
[-]2019-08-13: 说说你对app(或进程)启动流程的理解[/-][+]2019-08-13: 说说你对app(或进程)启动流程的理解?[/+]MicroKibaco commentedon Aug 13, 2019
App 启动流程
App启动流程 包括bootloader,Kernel,init,zygote和system_server.不过bootloader,Kernel已经偏操作系统内核和驱动方面了,不做细讲,这里从init开始带大家深入理解App启动流程和顺序.init
init是Linux用户的第一个进程,进程号是1,说这个主要目的是引入我们话匣子zygote,init是如何创建zygote以及init属性服务是如何工作的呢?代码很复杂,我也看不懂,你只要知道是通过
init.rc解析,然后执行各个阶段的动作,最后创建zygote就行了,当然还要处理socket属性服务方面的事情,因为涉及很多和Linux系统相关的知识.作为应用开发就没必要太关注这个了.zygote
当我上面没说,直接跳到
zygote,zygote中文意思是受精卵,他是Android系统牵动Java世界的纽带.而system_server人如其名,系统中重要的server都会驻留在Java中.zygote和system_server这两个进程分别是Java世界的半边天,任何进程的死亡,都会导致Java世界的Crash.zygote最初名字是android_process,这个名字是Android.mk文件被指定的,它本身就是个Native程序,和内核和驱动均无关.我们不需要深究太多,只要了解一点,
Zygote觉的自己工作压力太大,于是通过startSystemServer分裂system_server作为Java的世界服务.zygote被命名为受精卵一点都不过分,如果支持中文编码其实更适合盘古_女娲system_server
ZygoteInt调用startSystemServer创建system_server,system_server通过hsp方法完成自己的使命,并抛出异常,最终调用SystemServer引入main方法,main方法加载libandroid_server.so并调用native的init1函数,init1函数通过JNI调用init2函数,init2函数创建一个线程,用于加载各种service,init1函数最终加入Binder通信系统参考资源
1. 深入理解 Android
2. App系统启动流程分析
3. App 启动过程(含 Activity 启动过程) | 安卓 offer 收割基
liu1813565583 commentedon Aug 13, 2019
App的启动方式:
冷启动:当启动应用时,后台没有该应用的进程。这是系统会创建一个新的进程分配给该应用。这是app的冷启动。冷启动因为系统会分配一个新的进程给app,此时的app会创建Applocation,然后才回去创建MainActivity,最后显示在界面上。
热启动:当启动应用的时候,后台已经存在该应用的进程了,(列:按back和home应用虽然会退出但是应用的进程仍然在后台运行,可以进入任务列表查看)这个是热启动,因为热启动不会创建进程。所以app不会创建Applocation,只会初始化MainActivity。一个应用从创建到销毁只会执行一次Applocation。
应用的启动步骤:
(1) Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity
(2) ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态
(3) Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行
(4) ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信
(5) ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了
应用启动流程涉及到的类和对象:
(1) Launcher:Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity,实现了点击、长按等回调接口,来接收用户的输入。
(2) ActivityManagerServices:简称AMS,服务端对象,负责系统中所有Activity的生命周期。
(3) ActivityThread:App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作
(4) ApplicationThread:用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。
(5) ApplicationThreadProxy:是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。
(6) Instrumentation:每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。
(7) ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
(8) ActivityRecord:ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
(9) TaskRecord:AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。
App启动白屏或黑屏的原因:是因为已进入到Activity,但是未加载到布局文件,就先显示来windows窗口的背景。黑屏/白屏就是显示的windows背景(这个就是theme的设置)
App启动白屏或黑屏解决方案:
(1) 为Theme设置背景图(会给人一种快速加载的感觉)
<stylename="Theme.AppStartLoad"parent="android:Theme">
<itemname="android:windowBackground">@drawable/ipod_bg
<itemname="android:windowNoTitle">true
</style>(2) 为Theme设置透明属性(会给人较慢加载出来感觉)
<stylename="Theme.AppStartLoadTranslucent"parent="android:Theme">
<itemname="android:windowIsTranslucent">true
<itemname="android:windowNoTitle">true
</style>App的启动优化:
(1) Application的创建过程中尽量少的进行耗时操作
(2) 如果用到SharePreference,尽量在异步线程中操作
(3) 减少布局的层次,并且生命周期回调的方法中尽量减少耗时的操作
chengying1216 commentedon Aug 13, 2019
APP启动在项目中碰到过黑白屏的问题
为什么我的 APP 启动会白屏或者黑屏
有时候我们会发现,我们在启动我们自己的 APP 的时候,总是有那么点时间是白屏(黑屏),经过了白屏(黑屏)后才会进入我们的 APP。那么这是为什么呢?
有很多的初始化放到了 Application 中去完成了,那么这个时候刚打开程序的时候就会有个耗时,就会出现白屏的效果。
所以这里程序加载有个顺序,当打开一个 Activity 的时候,并且这个 Activity 所属的 Application 还没有运行,系统会首先为这个 Activity 创建一个进程,创建进程的时候就会调用 Application 的 onCreate 方法。进程的创建和 onCreate 内部的初始化是需要时间的,如果这个时候过长,没有任何反应的话,那么对于用户来说是不不知道的,用户还以为自己没有点到呢,所以很显然是不可能在原页面等待加载的,那么这个时候就有了 StartingWindow(PerviewWindow)的出现,StartingWindow 出现在应用程序进程创建并且初始化完成之前,是个临时的窗口,对应的 WindowType是 TYPE_APPLICATION_STARTING 作用就是告诉用户,系统已经收到我们的操作了,正在对程序进行初始化,只要初始化完毕后就会移除这个窗口。
所以其实我们看到的白屏或者黑屏就是 StartingWindow,那么为什么是白色或者黑色呢?我们一般都会给我们的 Application 和 Activity 设置 Theme,系统就会根据我们所设置的 Theme 来决定 StartingWindow 的颜色。我们都知道 Window 布局的顶层是 DecorView,而 StaringWindow 显示的是一个空的 DecorView,只是这个 DecorView 会应用我们的这个 Activity 所指定的 Theme。我们默认的 Theme 是 @android:style/Theme.Light 的话,这个时候就会产生白屏了。黑屏就是应用了 @android:style/Theme.Black,好了到这里我们就彻底明白为什么会出现白屏或者黑屏了。
App启动白屏或黑屏解决方案:
(1) 为Theme设置背景图(会给人一种快速加载的感觉)
<stylename="Theme.AppStartLoad"parent="android:Theme">
<itemname="android:windowBackground">@drawable/ipod_bg
<itemname="android:windowNoTitle">true
</style> (2) 为Theme设置透明属性(会给人较慢加载出来感觉)<stylename="Theme.AppStartLoadTranslucent"parent="android:Theme">
<itemname="android:windowIsTranslucent">true
<itemname="android:windowNoTitle">true
</style> App的启动优化:(1) Application的创建过程中尽量少的进行耗时操作
(2) 如果用到SharePreference,尽量在异步线程中操作
(3) 减少布局的层次,并且生命周期回调的方法中尽量减少耗时的操作
pioneerz commentedon Aug 13, 2019
app的启动流程分析:https://www.jianshu.com/p/28281b54d318
gys0000 commentedon Aug 13, 2019
首先放上我参考的文章,感觉写的不错。Android - Activity 启动过程
我先说一下我理解的一个应用启动的大致流程。
第一步我们点击桌面上一个应用图标,这个时候管理者会向系统服务进程发送一个指令:我要打开一个
activity;第二步既然要打开activity,总要有个新的进程装载吧,那么系统服务向最牛的进程,算是系统进程吧,发送创建A进程的请求,这个时候系统主进程会进行创建A进程的工作,先判断要创建的A进程是否存在,然后确定是否要创建A进程;第三步创建好A进程之后,A进程向系统服务进程说,我已经被创建好了,你可以给我发送我运行需要的东西了,然后系统服务进程就会向A进程发送指令,告诉A进程需要创建Application和activity等一系列操作。上面一系列啰嗦的叙述,其中系统服务进程是
system_server进程,最牛的系统主进程是Zygote进程,创建进程的操作是fock操作,判断进程的唯一性是查看ActivityManagerService中有没有A进程的ProcessRecord(可以理解为每个进程的uid+process)信息,创建A进程的同时在A进程中创建了ActivityThread;进程A中的ActivityThread向system_server进程的ActivityManagerService发送A进程创建好的指令,并把A进程中的ApplicationThread发给ActivityManagerService,然后system_server进程的ActivityManagerService通过ApplicationThreadProxy这个代理与进程中的ApplicationThread沟通,进一步在A进程中创建application和activity等这过程太复杂了,里边涉及了好多的点。只能大致的说一下,我再继续研究一下,有新的发现和想法再补充上来
ArtarisCN commentedon Aug 13, 2019
*
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);TrampcR commentedon Sep 10, 2019
App 启动过程
一、整体了解
1、ActivityManagerService
简称 AMS,服务端对象,负责管理 Activity 生命周期。
2、ActivityThread
App 的入口,启动 App 后,会调用 ActivityThread.main(),开启 Looper、MessageQueue,与 ActivityManagerService 配合完成对 Activity 的管理。
3、ApplicationThread
实现 ActivityManagerService 与 ActivityThread 之间的交互,在 ActivityManagerService 需要管理 Application 中 Activity 的生命周期时,通过 ApplicationThread 代理对象和 ActivityThread 通信。
4、ApplicationThreadProxy
ApplicationThread 在服务端的代理对象,负责和客户端的 ApplicationThread 进行通信。
5、Instrumentation
每个应用程序只有一个 Instrumentation 对象,每个 Activity 内都有一个对该对象的引用,可以理解为应用进程的管家,ActivityThread 需要创建或者暂停某个 Activity 时,都需要通过 Instrumentation 进行操作。
6、ActivityStack
Activity 在 AMS 中的栈管理,用来记录已经启动的 Activity 的先后顺序、状态信息等,通过 ActivityStack 决定是否需要启动新的进程。
7、ActivityRecord
ActivityStack 管理的对象,每个 Activity 在 AMS 对应一个 ActivityRecord,用来记录 Activity 的状态以及其他管理信息,其实就是服务器端 Activity 对象的映射。
8、TaskRecord
AMS 抽象出来的一个任务的概念,是记录 ActivityRecord 的栈,一个 Task 包含若干个 ActivityRecord,AMS 通过 TaskRecord 确保 Activity 启动和退出的顺序。
二、Zygote
在 Linux 中,所有的进程都是由 init 进程直接或间接 fork 出来的,Zygote 进程也不例外。
手机开机后,Linux 内核加载完成后,会启动一个 init 进程。
每一个 App 其实都是:
所以,在系统中的第一个 Zygote 进程启动之后,再打开一个 App,其实就是开启一个新的进程。而为了实现资源共用和更快的启动速度,Android 系统开启新进程的方式是:通过 fork 第一个 Zygote 进程开启新进程,换句话说,其他应用所在的进程都是 Zygote 的子进程。
三、SystemServer
SystemServer 是一个进程,也是由 Zygote 进程 fork 出来的。
系统里比较重要的服务都是从这个进程里开启的,比如 ActivityManagerService、WindowManagerService、PackageManagerService 等。
Zygote 开启的时候会调用 ZygoteInit.main()
四、ActivityManagerService
简称 AMS,服务端对象,负责系统中所有 Activity 生命周期。
初始化时机:SystemServer 进程开启时。
这是系统进程开启时的流程,在这之后,会开启系统的 Launcher 程序,完成系统界面的加载与显示。
五、Android 系统里面的服务器和客户端
服务器端:所有 App 共用的系统服务,比如 ActivityManagerService、PackageManagerService、WindowManagerService 等,当某个 App 要进行某项操作时,要告诉这些系统服务。
客户端:某个 App。
App A 调用 startActivity 不能直接打开 App B 的某个页面,而是通过一系列调用,告诉 AMS 要打开 App B 的某个页面,AMS 会通知 Zygote 进程 fork 一个新进程,来开启 App B。
App 与 AMS 之间通过 Binder 进行 IPC 通信,AMS 与 Zygote 之间通过 Socket 进行通信。
AMS 的用途:
六、Launcher
Launcher 本身也是一个应用程序。
七、Instrumentation 和 ActivityThread
每个 Activity 都持有 Instrumentation 对象的一个引用,但整个进程只会存在一个 Instrumentation 对象。
当 startActivityForResult() 调用之后,实际上还是调用了 mInstrumentation.execStartActivity()。
这个类里面的方法大多数和 Application 和 Activity 有关,这个类就是完成对 Application 和 Activity 初始化和生命周期的工具类。
AMS -> ActivityThread -> Instrumentation
八、AMS 与 ActivityThread 之间的 Binder 通信
ActivityManager.getService() 返回的就是 ActivityManagerService 的远程接口。
客户端:ActivityManagerProxy -> Binder驱动 -> ActivityManagerService:服务器
如果 AMS 想要通知 ActivityThread 做一些事情,还是通过 Binder 通信,不过是换成了 ApplicationThread 和 ApplicationThreadProxy。
ApplicationThreadProxy:服务器 -> Binder 驱动 -> 客户端:ApplicationThread
九、问答
1、一个 App 的程序入口到底是什么?
ActivityThread.main()。
2、整个 App 的主线程的消息循环是在哪里创建的?
是在 ActivityThread 初始化的时候,就已经创建消息循环了,所以在主线程里面创建 Handler 不需要指定 Looper,而如果在其他线程使用 Handler,则需要单独使用 Looper.prepare() 和 Looper.loop() 创建消息循环。
3、Application 是在什么时候创建的?onCreate()什么时候调用的?
也是在 ActivityThread.main() 的时候,再具体点,就是在 thread.attach(false) 的时候。
参考:APP启动过程