Hook 应用的入口 Activity

简介: 假如你现在要开发一个 SDK,比如说广告SDK吧,你希望在应用的入口 Activity 之前插入你的 Activity,在你的 Activity 中显示广告, 怎么做? 我看过联通沃商店的做法, 要求接入方声明自己的 Ativity 为入口 Activity,这种做法显然不符合一个技术人的追求的。

问题

前两天看到联通沃商店的 SDK 能让接入方应用的入口 Activity 在联通的闪屏页面结束之后出现, 我想他是不是采用什么黑科技 hook 了人家应用的入口 Activity? 反编译看了下,并无什么黑科技, 而是要求接入方声明它的闪屏页面为入口页面。那么能不能在接入方无知觉的情况下 hook 应用的入口 Activity,先 hold 住等我们自定义的 Activity 完成之后再进入?

问题再简化一下:如何 hook 一个应用的入口 Activity,插入自己的Activity?

思路

我们首先要知道一个应用的入口Activiy是怎么被创建,然后被现实出来的?如果看过插件化的相关实现文章就不难理解了,我们首先来看看用户点击启动图标之后是怎么进入第一个Activity的:

明白了Activity的创建和方法调用流程我们就可以决定在哪个环节 hook 了,不难发现,我们 hook 的最佳时间是 Activity 的 onCreate 方法被调用前, 也就是Instrumentation 的 callActivityOnCreate 方法,我们把它拦截掉, 怎么做?
你需要知道个知识点: 反射代理。我假定读我的文章的人都熟悉反射和代理了。

反射获取 Instrumentation

首先通过反射获取应用进程的 Instrumentation 对象,再来看看 Instrumentation 相关的引用关系:
ActivityThread -> Instrumentation
见 ActivityThread.java 中代码:

Instrumentation mInstrumentation;

现在我们想办法拿到 ActivityThread 的实例对象:

public static final ActivityThread currentActivityThread() {
 return sThreadLocal.get();
}

所以我们可以先反射 currentActivityThread() 方法拿到 ActivityThread 当前实例, 再反射 mInstrumentation 拿到 Instrumentation 对象。

      //获取当前的ActivityThread对象
        Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
        Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
        currentActivityThreadMethod.setAccessible(true);
        Object currentActivityThread = currentActivityThreadMethod.invoke(null);

        //拿到在ActivityThread类里面的原始mInstrumentation对象
        Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
        mInstrumentationField.setAccessible(true);
        Instrumentation mInstrumentation = (Instrumentation) 
      mInstrumentationField.get(currentActivityThread);

获取了 Instrumentation 对象怎么拦截里面的方法?如果是接口实现类直接使用 JDK 的动态代理就能实现拦截, 这里只能使用静态代理, 我们自己创建一个 Instrumentation 的子类 ,就叫 InstrumentationProxy 吧,InstrumentationProxy 代替原来的 Instrumentation。




   //包装代理
        Instrumentation evilInstrumentation = new InstrumentationProxy(mInstrumentation);

        // 偷梁换柱

        mInstrumentationField.set(currentActivityThread, evilInstrumentation);

InstrumentationProxy 的实现:

public class InstrumentationProxy extends Instrumentation {

 public static final String TAG = "InstrumentationProxy";
 public Instrumentation target;
 
 //通过构造函数来传递对象
 public InstrumentationProxy(Instrumentation mInstrumentation) {
     target = mInstrumentation;
 }
 @Override
public void callActivityOnCreate(Activity activity, Bundle icicle) {
           // 就在这儿,干你想干的坏事

        target.callActivityOnCreate(activity, icicle);
 }

}

设计实现

以上算是完成了可行性技术预研, 接下来回调我们开头提的那个业务问题,就是针对问题的设计了, 首次启动时 hook 入口Acitvity。

首次启动注入广告 Activity

demo

https://github.com/liuguangli/HookLaunchActivity

目录
相关文章
|
SQL 数据库
PowerDesigner导出SQL脚本运行注释出现乱码问题
PowerDesigner导出SQL脚本运行注释出现乱码问题
567 0
|
25天前
|
人工智能 Ubuntu Linux
最近 OpenClaw“养虾”突然爆火,到底怎么装?卓伊凡把 Windows 和 Ubuntu 安装步骤一次讲透
卓伊凡详解OpenClaw“养虾”安装:Windows推荐WSL2+Ubuntu方案,Linux直接一键脚本;涵盖环境要求、完整步骤、常见报错及排障技巧,并强调“会装≠真懂”,重在理解原理与工程能力。(239字)
3597 7
|
监控 关系型数据库 MySQL
深入了解MySQL主从复制:构建高效稳定的数据同步架构
深入了解MySQL主从复制:构建高效稳定的数据同步架构
462 1
|
人工智能 自然语言处理 PHP
通义灵码体验评测
通义灵码体验评测
822 2
|
运维 监控 Devops
【运维杂谈】DevOps是什么意思?
【运维杂谈】DevOps是什么意思?
907 0
|
JavaScript
vue中关于element的el-image 图片预览功能增加一个下载按钮
vue中关于element的el-image 图片预览功能增加一个下载按钮
1883 0
|
域名解析 网络协议 网络安全
阿里云DDoS高防(中国内地)计费说明
阿里云DDoS高防(中国内地)计费说明
|
XML 缓存 前端开发
Electron-builder 是如何打包 Windows 应用的?
本文首发于微信公众号“前端徐徐”,作者徐徐深入解析了 electron-builder 在 Windows 平台上的打包流程。文章详细介绍了 `winPackager.ts`、`AppxTarget.ts`、`MsiTarget.ts` 和 `NsisTarget.ts` 等核心文件,涵盖了目标创建、图标处理、代码签名、资源编辑、应用签名、性能优化等内容,并分别讲解了 AppX/MSIX、MSI 和 NSIS 安装程序的生成过程。通过这些内容,读者可以更好地理解和使用 electron-builder 进行 Windows 应用的打包和发布。
1110 0
|
应用服务中间件 Docker 容器
容器日志或文件提取
该步骤指导如何提取ftm服务的日志:首先选择服务并进入容器控制台,然后打包日志为ftm.tar.gz。接着,使用Xshell通过IP地址连接服务器,查找ftm容器ID,并使用docker cp命令将日志拷贝出来。再通过FTP工具将日志下载到桌面,最后从堡垒机下载日志包到本地。如果提取class文件,可直接在容器控制台路径下操作,无需打包。