Replugin源码详解

转载请注明链接:https://blog.csdn.net/feather_wch/article/details/88544574

Replugin源码详解

版本号:2019-03-13(23:59)


Replugin的职责划分

1、Replugin分为四个部分的源码

Replugin官方库工程 职责
replugin-host-gradle 【宿主的gradle插件】 1.动态修改AndroidManifest,生成占坑的四大组件 2.动态生成宿主的配置项HostBuildConfig.java 3.解析内置插件
replugin-host-library 【宿主依赖的核心库】1.初始化整个框架 2.hook ClassLoader 3.加载/启动/管理插件
replugin-plugin-gradle 【插件的gradle插件】1.利用Transfrom APIJavassit动态修改字节码,让插件工程的Activity全部继承自Replugin库的xxxActivity 等等
replugin-plugin-library 【插件依赖的库】1. 利用反射来使用宿主的接口和功能

2、replugin-host-gradle的职责

1.编译过程中,动态修改AndroidManifest,生成占坑的四大组件。

  • 位于xxx\app\build\intermediates\manifests\full\debug\AndroidManifest

2.动态生成宿主的配置项HostBuildConfig.java

  • 位于xxx\app\build\generated\source\buildConfig\debug\com\qihoo360\replugin\gen
// RePluginHostConfig.java
public class RePluginHostConfig {
   
    // 常驻进程名字
    public static String PERSISTENT_NAME = ":GuardService";
    // 是否使用“常驻进程”(见PERSISTENT_NAME)作为插件的管理进程。若为False,则会使用默认进程
    public static boolean PERSISTENT_ENABLE = true;
    // 背景透明的坑的数量(每种 launchMode 不同)
    public static int ACTIVITY_PIT_COUNT_TS_STANDARD = 2;
    public static int ACTIVITY_PIT_COUNT_TS_SINGLE_TOP = 2;
    public static int ACTIVITY_PIT_COUNT_TS_SINGLE_TASK = 2;
    public static int ACTIVITY_PIT_COUNT_TS_SINGLE_INSTANCE = 3;
    // 背景不透明的坑的数量(每种 launchMode 不同)
    public static int ACTIVITY_PIT_COUNT_NTS_STANDARD = 6;
    public static int ACTIVITY_PIT_COUNT_NTS_SINGLE_TOP = 2;
    public static int ACTIVITY_PIT_COUNT_NTS_SINGLE_TASK = 3;
    public static int ACTIVITY_PIT_COUNT_NTS_SINGLE_INSTANCE = 2;
    // TaskAffinity 组数
    public static int ACTIVITY_PIT_COUNT_TASK = 2;
    // 是否使用 AppCompat 库
    public static boolean ACTIVITY_PIT_USE_APPCOMPAT = true;
    //------------------------------------------------------------
    // 主程序支持的插件版本范围
    //------------------------------------------------------------
    // HOST 向下兼容的插件版本
    public static int ADAPTER_COMPATIBLE_VERSION = 10;
    // HOST 插件版本
    public static int ADAPTER_CURRENT_VERSION = 12;
}

3.解析内置插件,扫描assets/plugins,解析包含文件名、包名、版本、路径的plugins-builtin.json

  • 位于xxx\app\build\intermediates\assets\debug
// plugins-builtin.json
[
    {
        "high":null,
        "frm":null,
        "ver":1,
        "low":null,
        "pkg":"com.hao.repluginlogin",
        "path":"plugins/login.jar",
        "name":"login"
    }
]

3、replugin-host-library的职责

  1. 初始化整个框架
  2. hook ClassLoader
  3. 加载/启动/管理插件

4、replugin-plugin-gradle的职责

  1. 利用Transfrom APIJavassit动态修改字节码,让插件工程的Activity全部继承自Replugin库的xxxActivity
  2. 动态将插件Apk中调用LocalBroadcastManager的地方替换为Replugin库中的PluginLocalBroadcastManager
  3. 动态将ContentReolver、ContentProviderClient的调用替换成Replugin库中对应的调用
  4. 动态修改插件工程中所有调用Resource.getIdentifier()方法的地方,将第三个参数修改为插件工程的包名

5、replugin-plugin-library的职责

  1. 利用反射来使用宿主的接口和功能

初始化

核心原理

1、Replugin的核心底层原理?如何做到宿主和插件之间的通信和数据共享?

  1. 使用Binder机制
  2. 类似于ServiceManager和AMS
  3. 将一个常驻进程或者宿主的主进程作为Server端(根据配置选择)
  4. 其他的插件进程宿主进程全部属于Client端
  5. Server端:创建了一个Provider,通过Provider的query方法返回Binder对象来实现多进程之间、宿主和插件之间的通信和数据共享
  6. Server端作为插件管理进程,任务包括:插件的安装、卸载、更新、状态判断

2、Server端做了哪些事情?

  1. 创建了一个Provider,通过Provider的query()方法返回Binder对象来实现多进程之间、宿主和插件之间的通信和数据共享
  2. 处理: 插件的安装、卸载、更新、状态判断、提取优化dex文件
  3. 分配坑位
  4. 启动坑位

3、Replugin通过Hook ClassLoader如何处理Activity的启动?

  1. 能够对系统的类加载过程进行拦截
  2. 将之前分配的坑位信息替换为真正要启动的组件信息
  3. 并且使用该组件对应的ClassLoader进行类的加载

4、Replugin 启动四大组件的大致流程

  1. Client端,通知Server端,进行:
    1. 检查插件是否安装
    2. 安装插件
    3. 提取并优化dex文件
    4. 分配坑位
    5. 启动坑位(将真实组件的信息替换为坑位的信息)
  2. 利用坑位欺骗系统的检查
  3. 通过检查后Client开始真正加载目标组件
  4. 用Hook的ClassLoader对系统的类加载过程进行拦截
  5. 将坑位信息替换为真实组件的信息,并且用与其对应的ClassLoader进行类的加载

5、为什么要用与真实组件对应的ClassLoader去加载该组件?

关键字
Binder
ServiceManager和AMS
Server/Client
ContentProvider
ClassLoader

RePluginApplication

1、App在应用端所有的回调方法中,最早的一个回调方法是什么?

  1. Application的attachBaseContext()
  2. 该方法时ContextWrapper中的方法,在Application创建后,调用attach()时回调该方法
  3. 因此插件化框架中对系统ClassLoader等一切系统组件的Hook,都必须该方法中处理。避免不必要的故障。

2、RePluginApplication的源码分析

  1. 提供创建配置对象的方法
  2. 提供可创建RepluginCallbacks回调的空方法
  3. attachBaseContext()
  4. onCreate()
public class RePluginApplication extends Application {
   
  // 1、创建配置对象,提供可选的配置。
    protected RePluginConfig createConfig() {
   
        return new RePluginConfig();
    }
  // 2、创建RePluginCallbacks,能用于处理,例如插件不存在,启动下载流程,下载插件Apk
    protected RePluginCallbacks createCallbacks() {
   
        return null;
    }

    @Override
    protected void attachBaseContext(Context base) {
   
        super.attachBaseContext(base);

        RePluginConfig c = createConfig();
        if (c == null) {
   
          
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值