Android插件化之启动Activity(二)

本文详细介绍了如何通过Hook Instrumentation在Android中启动未在AndroidManifest.xml注册的Activity,包括三个步骤:插桩、请求启动时替换目标Activity、响应阶段还原目标Activity。关键在于理解Activity启动流程和Instrumentation的作用,并通过反射替换ActivityThread的Instrumentation来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

紧接上文Android插件化之启动Activity

Hook Instrumentation越过AndroidManifest检测

以上内容算是内功部分,接下来就到了学习具体招式的时候了。

要启动没有在AndroidManifest.xml中注册的Activity,其核心是就是偷天换日。怎么做呢?通过一个例子说明。

假如在插件中有一个未在AndroidManifest.xml注册的TargetActivity,我们想启动它,可以分为三步。

  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()分别完成第二步和第三步中的功能

再谈Instrumentation
ActivityThread中的Instrumentation

我们知道,每一个Java程序都有一个main()方法。Android App的main()方法就在ActivityThread中
在这里插入图片描述
在main()方法中,ActivityThread会被初始化并最终把对象保存在静态的sCurrentActivityThread中。在一个app进程中只有一个ActivityThread实例sCurrentActivityThread。sCurrentActivityThread可以通过ActivityThread.currentActivityThread()拿到。

attach()中,mgr.attachApplication(mAppThread)这段代码又是一个Binder双向通信的过程,它主要为创建Application对象服务。整个通信过程和Activity启动过程类似,我就不再详细介绍了。在通信的最后,ActivtiyThread.handleBindApplication()被调用,而在方法内部,Instrumentation被初始化。
在这里插入图片描述
总结一下,一个App进程,只有一个ActivityThread对象,这个对象保存在sCurrentActivityThread中,可以通过ActivityThread.currentActivityThread()获取。ActivityThread的mInstrumentation会在Application创建之前初始化。

Activity中的Instrumentation
Activtiy中的Instrumentation是通过Activity.attach()传进来的。
在这里插入图片描述
Activity.attach()在介绍Activity启动流程时提到过。它会在ActivityThread.performLaunchActivity()中被调用。
在这里插入图片描述
这样ActivtyThread把自己内部的Instrumentation传递到了Activity中。

Hook Instrumentation
通过以上分析,我们知道,要Hook app的Instrumentation,只需要替换掉ActivityThread的Instrumentation即可。但是,Android SDK没有为我们提供任何关于ActivityThread的api。要访问Android SDK中不存在的类或方法,我们学习一下VirtualAPK是怎么做的。

在VirtualAPK中有个叫AndroidStub的module。它的结构如下:
在这里插入图片描述
VirtualAPK又重新声明了这些Android SDK没有提供的Framework层的类。这些类只有方法的声明,如ActivityThread中的内容如下:
在这里插入图片描述
这样我们就可以使用这些Android SDK没有提供的类或隐藏的方法了。需要注意的一点是,AndroidStub应该只参与编译过程,这很简单,用compileOnly依赖就可以了。

接下来,我们就可以通过反射替换ActivitThread的Instrumentation了。代码如下:
在这里插入图片描述
上面的VAInstrumentation是对系统Instrumentation的代理类。在VAInstrumentation的内部我们可以加入任何我们想要的逻辑。

在Instrumentation.execStartActivity()执行前将我们要启动的Activity替换成预注册的ProxyActivity。
在这里插入图片描述
在Instrumentation.newActivity()执行前将预注册的ProxyActivity替换回我们要启动的Activity。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值