【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;
    }
}



目录
相关文章
|
Java Android开发
安卓虚拟摄像头过人脸,免root虚拟hook相机,虚拟相机hook版【jar】
两种Hook Android相机的方法:Xposed模块和Frida脚本。Xposed模块需要安装在已root的设备
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
384 6
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
504 3
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
288 0
|
Java API 开发工具
Android studio插件开发
Android studio插件开发
2159 5
Android studio插件开发
|
Android开发
Android Studio 插件开发详解四:填坑
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78265540 本文出自【赵彦军的博客】 插件打包 坑一 id不能重复 坑二插件描述信息要完整 坑三插件支持的产品要说明 总结 ...
1673 0
|
Java 开发工具 Android开发
Android Studio 插件开发详解一:入门练手
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78112003 本文出自【赵彦军的博客】 一:概述 相信大家在使用Android Studio的时候,或多或少的会使用一些插件,适当的配合插件可以帮助我们提升一定的开发效率,更加快乐。
2488 0
|
JSON Apache Android开发
Android Studio 插件开发详解二:工具类
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78112856 本文出自【赵彦军的博客】 在插件开发过程中,我们按照开发一个正式的项目来操作,需要整理一些常用工具类。
1689 0
|
开发工具 Android开发 Java
|
9月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1727 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡

热门文章

最新文章