【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )(三)

简介: 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )(三)

四、用于替换 ActivityThread 中 mH 中的 mCallback 静态代理类


静态代理 ActivityThread 中的 final H mH = new H() 成员中的 mCallback 成员 ;


该静态代理类的主要作用是 , 在创建的 Activity 示例类之前 , 使用插件包中的 Activity 组件替换之前在 AMS 调用之前使用的 占坑用的 Activity , 就是要创建 插件包 中的 Activity 类的实例对象 ;



1、获取 ClientTransaction 类


       

// 反射 android.app.servertransaction.ClientTransaction 类
            // 该类中有如下成员变量
            // private List<ClientTransactionItem> mActivityCallbacks;
            // 这个集合中存放的就是 android.app.servertransaction.LaunchActivityItem 类实例
            // 不能直接获取 LaunchActivityItem 实例 , 否则会出错
            Class<?> clientTransactionClass = null;
            try {
                clientTransactionClass =
                        Class.forName("android.app.servertransaction.ClientTransaction");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }



2、验证 msg.obj 类型是否合法


验证处理的信号 , 是否是对应 LaunchActivityItem , 如果不是 , 直接退出 ;


     

// 验证当前的 msg.obj 是否是 ClientTransaction 类型 , 如果不是则不进行 Intent 替换
            // 通过阅读源码可知 , 在 ActivityThread 的 mH 中, 处理 EXECUTE_TRANSACTION 信号时
            // 有 final ClientTransaction transaction = (ClientTransaction) msg.obj;
            if (!clientTransactionClass.isInstance(msg.obj)) {
                return true;
            }



3、反射获取 mActivityCallbacks 字段


     

// 反射获取
            // private List<ClientTransactionItem> mActivityCallbacks; 成员字段
            Field mActivityCallbacksField = null;
            try {
                mActivityCallbacksField =
                        clientTransactionClass.getDeclaredField("mActivityCallbacks");
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            // 设置成员字段可见性
            mActivityCallbacksField.setAccessible(true);



4、反射获取 mActivityCallbacks 成员对象


       

// 反射获取
            // private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
            Object mActivityCallbacksObject = null;
            try {
                mActivityCallbacksObject = mActivityCallbacksField.get(msg.obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }


5、使用插件 Activity 对应的 Intent 替换 LaunchActivityItem 类中的 mIntent 字段


遍历 ClientTransaction 中 private List mActivityCallbacks 成员对象 , 只针对 LaunchActivityItem 类型的元素进行后续处理 ;


获取 LaunchActivityItem 类中的 mIntent 成员变量 , 然后从其中获取 获取 启动 插件包 组件的 Intent , 使用该 Intent 替换之前的 mIntent 成员 ;


       

// 将
            // private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
            // 强转为 List 类型 , 以用于遍历
            List mActivityCallbacksObjectList = (List) mActivityCallbacksObject;
            for (Object item : mActivityCallbacksObjectList) {
                Class<?> clazz = item.getClass();
                // 只处理 LaunchActivityItem 的情况
                if (clazz.getName().equals("android.app.servertransaction.LaunchActivityItem")) {
                    // 获取 LaunchActivityItem 的 private Intent mIntent; 字段
                    // 该 Intent 中的 Activity 目前是占坑 Activity 即 StubActivity
                    // 需要在实例化之前 , 替换成插件包中的 Activity
                    Field mIntentField = null;
                    try {
                        mIntentField = clazz.getDeclaredField("mIntent");
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    }
                    mIntentField.setAccessible(true);
                    // 获取 LaunchActivityItem 对象的 mIntent 成员 , 即可得到 Activity 跳转的 Intent
                    Intent intent = null;
                    try {
                        intent = (Intent) mIntentField.get(item);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    // 获取 启动 插件包 组件的 Intent
                    Intent pluginIntent = intent.getParcelableExtra("pluginIntent");
                    if (pluginIntent != null) {
                        // 使用 包含插件包组件信息的 Intent ,
                        // 替换之前在 Ams 启动之前设置的 占坑 StubActivity 对应的 Intent
                        try {
                            mIntentField.set(item, pluginIntent);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }



6、完整代码示例


package kim.hsl.plugin;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.List;
/**
 * 静态代理 ActivityThread 中的 final H mH = new H() 成员
 */
public class HandlerProxy implements Handler.Callback {
    public static final int EXECUTE_TRANSACTION = 159;
    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == EXECUTE_TRANSACTION) {
            // 反射 android.app.servertransaction.ClientTransaction 类
            // 该类中有如下成员变量
            // private List<ClientTransactionItem> mActivityCallbacks;
            // 这个集合中存放的就是 android.app.servertransaction.LaunchActivityItem 类实例
            // 不能直接获取 LaunchActivityItem 实例 , 否则会出错
            Class<?> clientTransactionClass = null;
            try {
                clientTransactionClass =
                        Class.forName("android.app.servertransaction.ClientTransaction");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            // 验证当前的 msg.obj 是否是 ClientTransaction 类型 , 如果不是则不进行 Intent 替换
            // 通过阅读源码可知 , 在 ActivityThread 的 mH 中, 处理 EXECUTE_TRANSACTION 信号时
            // 有 final ClientTransaction transaction = (ClientTransaction) msg.obj;
            if (!clientTransactionClass.isInstance(msg.obj)) {
                return true;
            }
            // 反射获取
            // private List<ClientTransactionItem> mActivityCallbacks; 成员字段
            Field mActivityCallbacksField = null;
            try {
                mActivityCallbacksField =
                        clientTransactionClass.getDeclaredField("mActivityCallbacks");
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            // 设置成员字段可见性
            mActivityCallbacksField.setAccessible(true);
            // 反射获取
            // private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
            Object mActivityCallbacksObject = null;
            try {
                mActivityCallbacksObject = mActivityCallbacksField.get(msg.obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            // 将
            // private List<ClientTransactionItem> mActivityCallbacks; 成员字段实例
            // 强转为 List 类型 , 以用于遍历
            List mActivityCallbacksObjectList = (List) mActivityCallbacksObject;
            for (Object item : mActivityCallbacksObjectList) {
                Class<?> clazz = item.getClass();
                // 只处理 LaunchActivityItem 的情况
                if (clazz.getName().equals("android.app.servertransaction.LaunchActivityItem")) {
                    // 获取 LaunchActivityItem 的 private Intent mIntent; 字段
                    // 该 Intent 中的 Activity 目前是占坑 Activity 即 StubActivity
                    // 需要在实例化之前 , 替换成插件包中的 Activity
                    Field mIntentField = null;
                    try {
                        mIntentField = clazz.getDeclaredField("mIntent");
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    }
                    mIntentField.setAccessible(true);
                    // 获取 LaunchActivityItem 对象的 mIntent 成员 , 即可得到 Activity 跳转的 Intent
                    Intent intent = null;
                    try {
                        intent = (Intent) mIntentField.get(item);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    // 获取 启动 插件包 组件的 Intent
                    Intent pluginIntent = intent.getParcelableExtra("pluginIntent");
                    if (pluginIntent != null) {
                        // 使用 包含插件包组件信息的 Intent ,
                        // 替换之前在 Ams 启动之前设置的 占坑 StubActivity 对应的 Intent
                        try {
                            mIntentField.set(item, pluginIntent);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return false;
    }
}



目录
相关文章
|
4月前
|
SQL 人工智能 Dart
Android Studio的插件生态非常丰富
Android Studio的插件生态非常丰富
257 1
|
6天前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
54 19
|
4月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
5月前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
3月前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
4月前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
154 2
|
5月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
108 1
|
4月前
|
前端开发 Java 测试技术
android MVP契约类架构模式与MVVM架构模式,哪种架构模式更好?
android MVP契约类架构模式与MVVM架构模式,哪种架构模式更好?
140 0
|
5月前
|
Android开发
我是一位Android工程师,用通义灵码的AS插件做开发工作助手,对比之前没有灵码,现在提效了60%
我是一位Android工程师,用通义灵码的AS插件做开发工作助手,对比之前没有灵码,现在提效了60%
162 0
|
安全 Java Android开发
【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )
【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )
260 0
【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )

热门文章

最新文章