Android 11: Activity的启动流程

news/2024/7/6 21:22:58/文章来源:https://www.cnblogs.com/kato-T/p/18284531

客户端

ContextImpl.java -> startActivity(Intent intent, Bundle options)Instrumentation.java -> execStartActivity(...)
{...//ActivityTaskManager利用binder,从客户端调用服务端的函数 1.0int result = ActivityTaskManager.getService().startActivity(whoThread,who.getBasePackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);checkStartActivityResult(result, intent);//检查启动Activity的结果,看是否存在异常 比如1.1... 
}//1.0 引用
/*  ActivityTaskManager.java
public static IActivityTaskManager getService() {return IActivityTaskManagerSingleton.get();
}@UnsupportedAppUsage()
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =new Singleton<IActivityTaskManager>() {@Overrideprotected IActivityTaskManager create() {inal IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);return IActivityTaskManager.Stub.asInterface(b);}
};*///1.1
checkStartActivityResult(int res, Object intent)
{...case ActivityManager.START_INTENT_NOT_RESOLVED:case ActivityManager.START_CLASS_NOT_FOUND:if (intent instanceof Intent && ((Intent)intent).getComponent() != null)throw new ActivityNotFoundException("Unable to find explicit activity class "+ ((Intent)intent).getComponent().toShortString()+ "; have you declared this activity in your AndroidManifest.xml?");throw new ActivityNotFoundException("No Activity found to handle " + intent);case ActivityManager.START_PERMISSION_DENIED:throw new SecurityException("Not allowed to start activity "+ intent);...
}

服务端

ActivityTaskManagerService.java -> startActivityAsUser(...){...// TODO: Switch to user app stacks here.return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(opts).setUserId(userId).execute();...
}
/*
obtainStarter()方法实际是调用了mFactory.obtain(),
而mFactory为ActivityStarter的内部类DefaultFactory,看下DefaultFactory的obtain()frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.javastatic class DefaultFactory implements Factory {private final int MAX_STARTER_COUNT = 3;private SynchronizedPool<ActivityStarter> mStarterPool =new SynchronizedPool<>(MAX_STARTER_COUNT);public ActivityStarter obtain() {ActivityStarter starter = mStarterPool.acquire();if (starter == null) {if (mService.mRootWindowContainer == null) {throw new IllegalStateException("Too early to start activity.");}starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);}return starter;}
}obtain()的目的是拿到一个ActivityStarter对象,用来启动activity.
每个Intent对应一个ActivityStarter这里使用了SynchronizedPool--简单的对象池来管理对象的生产,
对象池里有3个对象,如果申请时池子里没有可用对象,则直接new一个!
*/
ActivityStartController.java -> execute()ActivityStarter.java -> executeRequest()
{...(合法性检查abort)2.0 权限检查 (ActivityStackSupervisor)mSupervisor.checkStartAnyActivityPermission()2.1 是否能后台启动  shouldAbortBackgroundActivityStart()2.2 拦截器  (ActivityStartInterceptor)mInterceptor.setStates() 例如,因为目标用户当前处于静默状态模式(关闭工作)或目标应用程序被挂起.通过ActivityStartInterceptor检查各种拦截情况,如认为是潜在的恶意app(HarmfulApp)则改变intent为警告页面,到时不会跳转到原请求的activity2.3 权限回顾 isPermissionsReviewRequired() 如果需要在启动真正目标activity前跳转到权限review页面,则将原intent改为pending Intent传给review页面,待review结束后再继续启动//2.4 Instant app(ephemeral app)启动ephemeral installer2.5 创建ActivityRecord , final ActivityRecord r = new ActivityRecord(mService,..)...}
-> startActivityUnchecked(...) -> startActivityInner(...) 
{在ActivityStarer::startActivityInner方法中,通过getOrCreateRootTask()创建Task,而后通过setNewTask方法将新建的ActivityRecord进行挂在到新建的Task上.这一步AMS吧ActivityRecord和Task创建并且挂载到层级树,接下来是处理新的Activity启动和显示
}
RootWindowContainer
//堆栈打印RootWindowContainer.java->resumeFocusedStacksTopActivities()->ActivityStack::resumeTopActivityUncheckedLocked()
{...if (!resumedOnDisplay) {/*如果没有可用的activity在栈顶的时候,例如,设备刚刚启动或启动器崩溃,程序会请求恢复集中堆栈中的顶部活动,确保至少在home活动被启动和恢复*/final ActivityStack focusedStack = display.getFocusedStack();if (focusedStack != null) {result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);} else if (targetStack == null) {result |= resumeHomeActivity(null /* prev */, "no-focusable-task",display.getDefaultTaskDisplayArea());}}...
}/*
RootWindowContainer::resumeFocusedTasksTopActivitiesTask::resumeTopActivityUncheckedLockedTask::resumeTopActivityInnerLockedTaskFragment::resumeTopActivity TaskDisplayArea::pauseBackTasks  --   2.2.1 pause LauncherActivity WindowContainer::forAllLeafTaskTaskFragment::forAllLeafTaskFragmentsTaskFragment::startPausingTaskFragment::startPausingTaskFragment::schedulePauseActivity --构建 PauseActivityItem,这里是触发暂停launchActivityTaskManagerService::startProcessAsync     -- 2.2.2创建app进程*/->ActivityStack::resumeTopActivityInnerLocked()-> ActivityStack::resumeTopActivityInnerLocked()-> ActivityStack::startPausingLocked()
{...ActivityRecord prev = mResumedActivity;...mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,prev.configChangeFlags, pauseImmediately));...
}->ClientLifecycleManager::scheduleTransaction() -> ClientTransaction::schedule()->ApplicationThread::scheduleTransaction() -> ClientTransactionHandler::scheduleTransaction()->ClientTransactionHandler::sendMessage()->内部类 H extends Handler 收到消息 case -> TransactionExecutor::performLifecycleSequence()
ActivityThread
//下面是重点
/*
ActivityThread::handleLaunchActivityActivityThread::performLaunchActivityInstrumentation::newActivity --- 创建ActivityActivity::attach  ---处理Window相关Window::initWindow::setWindowManagerInstrumentation::callActivityOnCreate ---onCreate流程Activity::performCreateActivity::onCreate  --activity流程over
*/
-> ActivityThread::handleLaunchActivity(...)-> ActivityThread::performLaunchActivity(...)
{...Activity activity = null;try {java.lang.ClassLoader cl = appContext.getClassLoader();//创建Activityactivity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();if (r.state != null) {r.state.setClassLoader(cl);}} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to instantiate activity " + component+ ": " + e.toString(), e);}}...//执行attach,内部创建Windowactivity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken);...//通知activityif (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}...}-> Instrumentation::newActivity(...) -> Instrumentation::callActivityOnCreate(...)// perform 执行
-> Activity::performCreate() ->Activity::onCreate()

【Android 13源码分析】Activity启动流程-2 -

Android 11源码分析: Activity的启动流程 -

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738224.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mirai Bot初始化配置

RT其实本来我的bot已经因为自己手贱登陆qq nt直接报废了,但是论坛里有佬提供了新的协议库,那这不赶紧复活bot都对不起这个新的协议库。 本文写于2024年7月4日19:20:21,可能随着时间久远而无法实现功能。由于存在下载障碍,所以这里也搞了个存档,本帖中的相关标星*资源无法下…

量化曲线的平滑程度

思路 1. 对原始数据一阶求导,得到一阶导数数组。 2. 对一阶导数数组求标准差。导数的标准差提供了导数值的波动性,标准差越小,曲线越平滑。 平滑曲线import numpy as np import matplotlib.pyplot as plt from matplotlib import font_manager fname="/usr/local/pytho…

Android常见错误

错误1 A problem occurred configuring root project ����ʶ��. > Could not resolve all files for configuration :classpath.> Could not resolve com.android.tools.build:gradle:8.4.0.Required by:project : > com.android.application:com.android.appli…

MyBatis中的Where标签:提升你的SQL查询效率

哈喽,大家好,我是木头左!理解MyBatis的Where标签 MyBatis是一款优秀的持久层框架,它提供了许多强大的标签来帮助编写更优雅、高效的SQL语句。其中,<where>标签是使用频率极高的一个,它能够自动处理查询条件,使得的SQL语句更加简洁和高效。在这篇文章中,将深入探讨…

Java中的JSON神器,如何轻松玩转复杂数据结构

哈喽,大家好,我是木头左!一、揭秘JSON世界的基石 在Java的世界中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于文本,易于阅读和编写,同时也易于机器解析和生成。JSON在日常开发中的应用非常广泛,无论是前后端的数据交互,还是配置文件的读取,…

《Python 第三方模块包安装指南》

在 Python 编程中,第三方模块包极大地丰富了其功能,让我们能够更高效地完成各种任务。下面将为您详细介绍如何安装 Python 的第三方模块包。 一、使用 pip 命令安装 pip 是 Python 的包管理工具,大多数情况下,我们可以通过以下命令来安装第三方模块包:pip install 模块包名…

巴图自动化Modbus转PN网关模块连智能仪表与PLC通讯

通过巴图自动化Modbus转Profinet协议网关模块,实现PLC对仪表设备的远程监控和数据传输,提高生产效率和运行稳定性。巴图自动化Modbus转Profinet协议转换BT-MDPN100网关模块的主要功能是实现Modbus协议和Profinet协议之间的转换和通信。Modbus 转 Profinet协议网关模块集成了M…

一文搞懂到底什么是 AQS

日常开发中,我们经常使用锁或者其他同步器来控制并发,那么它们的基础框架是什么呢?如何实现的同步功能呢?本文将详细用白话讲解构建锁和同步器的基础框架--AQS,并根据源码分析其原理。前言 日常开发中,我们经常使用锁或者其他同步器来控制并发,那么它们的基础框架是什么…

flutter状态管理 provider使用

provider是flutter官方推荐的状态管理插件,是基于InheritedWidget实现的。 下面我们来讲一个provider的使用方法。 1.在pubspec.yaml文件中添加 provider: ^6.1.2 开发文档:https://pub-web.flutter-io.cn/packages/provider 可以查看使用方法和最新版本号。 添加完成后…

企业数字化转型:顶层规划方法

随着数字化时代的到来,发生了以数字化、智能化为典型特征的新一轮科技革命,各行各业利用互联网、大数据、云计算、人工智能、区块链技术对传统产业进行全方位、全链条改造,实施“上云用数赋智”行动,全面推进各行业数字化转型。数字经济的大门已然开启,数字经济顶层战略规…

Nuxt3 的生命周期和钩子函数(十)

摘要:本文详细介绍了Nuxt3框架中的五个webpack钩子函数:webpack:configResolved用于在webpack配置解析后读取和修改配置;webpack:compile在编译开始前调用,可修改编译选项;webpack:compiled在编译完成后调用,可处理编译结果;webpack:change在开发模式下文件变化时触发,…

Jenkins汉化

1、Jenkins版本:版本2.426.3) Manage Jenkins->选择Plugins->切换到Availabled plugin->搜索local,然后选中安装,如下图所示 2、安装完成后重启Jenkins,汉化完成。如下图所示 像个小学生一样努力学习

模拟集成电路设计系列博客——9.1 比较器

模拟集成电路设计 9.1 比较器 比较器可能是继放大器之后第二常用的电路元件,比较器用于判断一个信号是否大于或小于零,或者比较一个信号是否大于另一个。如我们之前的章节所见,比较器在ADC中非常常用。在其他的应用中也经常出现比较器,例如数据传输,开关电源稳压器等等。 …

prufer序列

prufer序列用途: 将带标号的树用唯一的整数序列表示出来,证明凯莱公式。构造方法:每次选择一个编号最小的叶结点并删掉它,然后在序列中记录下它连接到的那个结点。重复\(n-2\)次后就只剩下两个结点,算法结束。 举个栗子(本图来自baoziwu2,侵删)显然可以有一个用堆做的方法,…

【冷启动#2】实用的springboot tutorial入门demo

跟着官方文档熟悉一遍创建spring工程的步骤 https://spring.io/guides/gs/spring-boot https://juejin.cn/post/7077958723829760008 demo简介 整个demo的预期目标是: 管理一堆玩家的数据,数据库使用的是现成的我们虚拟机上安装的MySQL 项目结构参考 主要工作:创建并熟悉spr…

CentOS8部署zerotier异地组网

本文介绍了在CentOS 8系统上部署ZeroTier以实现异地组网的方法,包括安装、配置、加入网络、开启IP转发和设置路由表等步骤,并提出进一步实现公网无缝组网的展望。CentOS8部署zerotier异地组网 CentOS8部署zerotier异地组网 一、前言 本文在此前研究部署FRP进行内网穿透,但FR…

《DNK210使用指南 -CanMV版 V1.0》第九章 打印输出实验

第九章 打印输出实验 1)实验平台:正点原子DNK210开发板 2)章节摘自【正点原子】DNK210使用指南 - CanMV版 V1.0 3)购买链接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-DN…

分享一款可编辑本地电脑文件的在线编辑器

之前见过在线版的VSCode,被惊讶到了。网页上竟然可以编辑电脑本地的文件,打破了网页无法编辑本地电脑文件的限制。一直好奇怎么做的。抽空研究了一下,然后发现其实也不难。背景 之前见过在线版的VSCode,被惊讶到了。网页上竟然可以编辑电脑本地的文件,打破了网页无法编辑本…

xhcms

xhcms 目录结构 admin --管理后台文件夹 css --存放css的文件夹 files --存放页面的文件夹 images --存放图片的文件夹 inc --存放网站配置文件的文件夹 install --网站进行安装的文件夹 seacmseditor --编辑器文件夹 templ…

lrzsz安装完成后rz乱码

rz选择文件夹后乱码传输不到linux里面, 这时候只需要rz -be再选择文件 这样就可以进行后续的解压了tar -zxvf jdk-8u65-linux-x64.tar.gz