12.源码阅读(app启动流程-android api 26)
activity的启动流程之前已经通过源码了解了,那么app的启动流程是怎样的,从我们按下app的图标,到应用启动起来显示出画面,中间都经历了什么?
安卓是基于java的,所以和java有一定的相似性,一个java程序的起点是main,那么android是不是也是如此?事实上,正如猜想我们找到ActivityTread这个类中的main方法,这里就是app启动的源头
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); //初始化内存卡环境 Environment.initForCurrentUser(); // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); //处理签名相关的东西,验证之类的饿 AndroidKeyStoreProvider.install(); // Make sure TrustedCertificateStore looks in the right place for CA certificates //用户目录相关的东西 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); //应用程序一启动就初始化全局的looper Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); //这个是主要的方法,false表示不是系统应用,第三方app默认都是false thread.attach(false); //初始化主线程handler,在ActivityTread加载的时候就已经生成了 if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
正式开始加载app
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { //第三方应用 //ViewRootImpl相关 ...... //这个已经很熟悉了,我们要去找IActivityManager的实现类ActivityManagerService final IActivityManager mgr = ActivityManagerNative.getDefault(); try { //进入ActivityManagerService mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } //可以看到这里是内存使用量的一个监听,当app已经占用的空间大于系统分配给 //这个app最大空间的四分之三的时候,java虚拟机会触发gc清理空间 BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { } } } }); } else { //系统应用 // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); mInitialApplication = context.mPackageInfo.makeApplication(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); } } // add dropbox logging to libcore DropBox.setReporter(new DropBoxReporter()); //设置Configuration改变的监听 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public void onConfigurationChanged(Configuration newConfig) { synchronized (mResourcesManager) { // We need to apply this change to the resources // immediately, because upon returning the view // hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { // This actually changed the resources! Tell // everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(newConfig)) { mPendingConfiguration = newConfig; sendMessage(H.CONFIGURATION_CHANGED, newConfig); } } } } @Override public void onLowMemory() { } @Override public void onTrimMemory(int level) { } }); }
进入ActivityManagerService
@Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } }
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ...... //thread就是传过来的final ApplicationThread mAppThread = new ApplicationThread();它在ActivityThread加载的时候就已经创建 thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); ...... // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } // Find any services that should be running in this process... if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } } ......
回到ActivityThread中
public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) { if (services != null) { // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } setCoreSettings(coreSettings); /* * Two possible indications that this package could be * sharing its runtime with other packages: * * 1.) the sharedUserId attribute is set in the manifest, * indicating a request to share a VM with other * packages with the same sharedUserId. * * 2.) the application element of the manifest has an * attribute specifying a non-default process name, * indicating the desire to run in another packages VM. * * If sharing is enabled we do not have a unique application * in a process and therefore cannot rely on the package * name inside the runtime. */ IPackageManager pm = getPackageManager(); android.content.pm.PackageInfo pi = null; try { pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId()); } catch (RemoteException e) { } if (pi != null) { boolean sharedUserIdSet = (pi.sharedUserId != null); boolean processNameNotDefault = (pi.applicationInfo != null && !appInfo.packageName.equals(pi.applicationInfo.processName)); boolean sharable = (sharedUserIdSet || processNameNotDefault); // Tell the VMRuntime about the application, unless it is shared // inside a process. if (!sharable) { VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir, appInfo.processName); } } AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data); }
handler接收消息进行处理
case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
private void handleBindApplication(AppBindData data) { ...... //反射加载到Instrumentation对象或者当条件不满足时,直接new出来 try { java.lang.ClassLoader cl = instrContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate instrumentation " + data.instrumentationName + ": " + e.toString(), e); } .... else { mInstrumentation = new Instrumentation(); } ...... try { //调用Application的onCreate 方法 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } }
Application是启动了,那么到了这里似乎已经无法继续往下走了,activity是如何启动的,我们回到ActivityManagerService中,在上边的那代码下如下,现在已经知道了bindApplication最终执行到了Application的onCreate,那么下边的方法attachApplicationLocked将会是寻找Activity启动的线索
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ...... //thread就是传过来的final ApplicationThread mAppThread = new ApplicationThread();它在ActivityThread加载的时候就已经创建 thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); ...... // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } // Find any services that should be running in this process... if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } } ......
attachApplicationLocked
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { final String processName = app.processName; boolean didSomething = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); if (!isFrontStack(stack)) { continue; } ActivityRecord hr = stack.topRunningActivityLocked(null); if (hr != null) { if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) { try { //真的开始启动activity了 if (realStartActivityLocked(hr, app, true, true)) { didSomething = true; } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting activity " + hr.intent.getComponent().flattenToShortString(), e); throw e; } } } } } if (!didSomething) { ensureActivitiesVisibleLocked(null, 0); } return didSomething; }
到了realStartActivityLocked这个方法这里,后边的东西就和之前看过的activity的启动流程相同了,所以就不再往下看了,感兴趣可以看看我的另一篇03.源码阅读(Activity启动流程--android api 23)
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【阿里聚安全·安全周刊】 全美警局已普遍拥有破解 iPhone 的能力 | 女黑客破解任天堂Switch,称硬件漏洞无法修复
本周的七个关键词:破解 iPhone丨女黑客破解任天堂丨假的身份证丨扫黄打非丨华盛顿特区发现手机间谍设备丨Telegram被俄罗斯监管机构告上法庭丨价值5万美金的Firefox浏览器漏洞 -1-【iOS】全美警局已普遍拥有破解 iPhone 的能力 来源:MacX ------------------------------------------------------ 来自 Motherboard 的报道称,目前全美范围内的当地警署以及联邦机构都可以很轻易的获取到解锁iPhone的专用工具,绕过加密手段轻松解锁嫌疑人的 iPhone,即使设备更新至最新版的操作系统也没有问题。 执法机关使用的是一种被称作 GrayKey 的解密工具,据称可以在数小时内解锁 4 位 iPhone 密码,不过 6 位密码可能需要花上
- 下一篇
Android ConstraintLayout按比例缩放View
Android ConstraintLayout按比例缩放View 关键点有两个,第一,使用Android ConstraintLayout的layout_constraintDimensionRatio属性,设置宽高比缩放比例,宽:高。第二,恒定宽和高,另外一个方向就会按照比例缩放。 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text0" android:layout_width="0dp" android:layout_height="100dp" android:background="@andro...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8