• 面试:插件化相关---activity


    我们先来看下Android常规Activity的启动流程

    如何评价360的Android插件化框架RePlugin? - 知乎

    1、调用Context.startActivity -> ActivityManagerProxy -> AMS, AMS通过Intent从PMS拿到ActivityInfo并创建ActivityRecord和token放入前台ActivityStack,接着按需启动Activity所属进程

    2、进程启动后,马上执行入口ActivityThread.main并调用attachApplication将启动信息反馈到AMS,AMS通过pid找到对应的ProcessRecord并更新其数据

    3、从前台ActivityStack中拿到栈顶的ActivityRecord,如果其proecssrecord为null,并且uid和processname跟新创建的ProcessRecord一致,则正式调用app.thread.scheduleLaunchActivity

    4、ActivityThread在scheduleLaunchActivity中创建ActivityClientRecord,用于跟AMS中的ActivityRecord对应,ActivityClientRecord最重要的两个字段是token和activityinfo,token用于关联ActivityRecord,activityinfo则包含activity的描述和所属包等信息

    5、在scheduleLaunchActivity内部接着发送LAUNCH_ACTIVITY message到mH这个handler,mH收到LAUNCH_ACTIVITY message后执行handleLaunchActivity

    请求阶段:

    ActivityManagerProxy是ActivityManagerService在app进程中的Binder代理对象。调用ActivityManagerProxy.startActivity()最后会调用ActivityManagerService.startActivity()。这样请求就到了ActivityManagerService

    响应阶段:

    在不考虑多进程的情况下,Activity的启动过程是一个Binder双向通信的过程。AMS要主动与app进程通信要依靠请求启动Activity阶段传过来的IBinder对象,这个IBinder对象就是上面介绍过的Instrumentation.execStartActivity()中的 whoThread对象,它实际上是一个ApplicationThreadProxy对象,用来和ApplicationThread通信。AMS通知app进程启动Activity是通过调用ApplicationThreadProxy.scheduleLaunchActivity()完成的。根据Binder通信,ApplicationThread.scheduleLaunchActivity()会被调用。

    1. scheduleLaunchActivity()将从AMS中传过来的参数封装成ActivityClientRecord对象,然后将消息发送给mH,mH是一个Handler对象。
    2. H是ActivityThread的内部类,继承自Handler,它在收到LAUNCH_ACTIVITY的消息后,会调用ActivityThread.handlerLaunchActivity()。
    3. handleLaunchActivity()主要调用了两个方法:performLaunchActivity()和handleResumeActivity()。performLaunchActivity()会完成Activity的创建,以及调用Activity的onCreate()、onStart()等方法。handleResumeActivity()会完成Activity.onResume()的调用。

    假如在插件中有一个未在AndroidManifest.xml注册的TargetActivity,我们想启动它,可以分为三步。Activity启动流程和插件化原理 - 掘金

    1. 在AndroidManifest.xml中预先注册一个我们项目中没有的Activity,例如ProxyActivity。我们把这种行为称为插桩。
    2. 在请求启动Activity阶段,我们把TargetActivity替换成AndroidManifest中预先注册的ProxyActivity。
    3. 在AMS响应阶段,Activity实例产生之前,我们再做一个完全相反的动作。即把响应信息中要启动的ProxyActivity替换回TargetActivity。

    第一步十分简单,没什么好说的。要实现第二步和第三步就需要用到Activity启动流程的知识了。 在Activity启动流程中,Instrumentation无论在请求阶段还是响应阶段都扮演着重要的角色。在请求阶段Instrumentation.execStartActivity()会被调用,而在响应阶段Instrumentation.newActivity()会被调用。因此如果我们可以Hook Instrumentation,那么我们就可以在execStartActivity()和newActivity()分别完成第二步和第三步中的功能。

    最终目的:Hook Instrumentation

    1、通过反射替换ActivitThread的Instrumentation

    2、Instrumentation.execStartActivity()执行前将我们要启动的Activity替换成预注册的ProxyActivity

    3、在Instrumentation.newActivity()执行前将预注册的ProxyActivity替换回我们要启动的Activity

  • 相关阅读:
    selenium爬虫如何绕过反爬,看这一篇文章就足够了
    【暑期每日一题】洛谷 P7694 [COCI2009-2010#4] AUTORI
    高级性能测试系列《18.csv数据文件设置:遇到文件结束符再次循环?遇到文件结束符停止线程?线程共享模式。》...
    MySQL主从复制(基于Centos7)
    QT创建子目录项目,可以让项目组织成树形结构的示例:在项目中同时创建Application和第三方动态库(内部)
    用 Rcpp 访问 C++ 代码
    【FreeRTOS】10 事件标志组
    转载 | 自动驾驶数据服务市场占有率居首,这家公司是如何做到的?
    流水线的实现
    Centos7 Shell编程之正则表达式、文本处理工具
  • 原文地址:https://blog.csdn.net/cpcpcp123/article/details/128108616