Android插件化原理(二)—启动插件Activity

本文详细解析了Android插件化的实现原理,包括如何加载插件APK/Dex,启动插件Activity,并通过Hook AMS和ActivityThread的Handler(H)来绕过Manifest校验,实现插件Activity的启动。文章介绍了核心思想,具体步骤,并提供了相关源码,展示了Hook过程的关键部分。

涉及到的同系列往期文章:


本篇文章目录:

1 原理

1.1 涉及到的Framework原理

回顾第一篇Android插件化原理(一)—— 插件类加载、类加载原理、(双亲委托机制)两点:

  1. 类加载器

为什么要说ClassLoader呢,因为class 都是由ClassLoader加载的,应用的所有类都在类加载器中。

  • DexClassLoader 8.0之前提供给系统使用,8.0之后与PathClassLoader并无区别
  • PathClassLoader ,8.0之前提供给开发者使用,用于加载应用class文件,例如CustomActivity、CustomeFragment,包括三方jar、apk、库的class;8.0之后与DexClassLoader并无区别;
  • BootClassLoader:用于加载Framework的class文件,例如Activity、Fragment
  1. 加载插件类原理:
  • 创建插件的DexClassLoader类加载器,通过反射获取插件的dexElements
  • 获取宿主的PathClassLoader类加载器,通过反射获取宿主的dexElements
  • 合并宿主的dexElements和插件的dexElements,生成新的Element[]对象
  • 通过反射把新的Element[]复制给宿主的dexElements。

以及StartActivity原理(二)——Android9.0 startActivity原理,Activity启动原理提到的

  1. Activity启动原理:
    在这里插入图片描述

app进程告知AMS要启动activity,AMS检测Activity存在后,返回目标activity的类信息,并通知app进程构造插件Activity实例;

1.1 核心思想
  • 启动插件的activity;
  • 检测到启动的是插件Acitivity,将其hook成宿主app的ProxyActivity;
  • AMS检测完成后,app启动ProxyActivity时,将其hook成我们的插件Activity。
1.2 具体原理

上面三步虽然简单,但是要明白为什么这么做?这么做原因有两点:

  1. 目标插件activity不在宿主Manifest清单文件中;
  2. 启动Activity需要通过AMS检测(manifest)。

所以在启动插件Activity的时候需要将intent的插件Activity hook成宿主的ProxyActivity去通过AMS检测,ProxyActivity在宿主app中,可以添加到Manifest清单文件中,自然可以通过检测;最后在启动阶段,将ProxyActivity再次hook成我们的插件Activity,最后在app进程可以构造其实例;

实现步骤

  • 加载插件apk/dex
  • 启动插件Activity,并添加标志位表明启动插件Activity;
  • Hook AMS,检测到intent中的标志位,替换插件Activity为ProxyActivity;
  • hook ActivityThread的Handle——H,在handleLaunchActivity对应的的messageWhat,检测intent中的标志位;
  • 将ProxyActivity重新替换成插件Activity;

附简单流程图:

在这里插入图片描述

2 实现

  • 1.准备工作

public class ProxyActivity extends AppCompatActivity {
   
   

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
   
        super.onCreate(savedInstanceState);
    }
}



public abstract class BaseActivity extends Activity {
   
   

    protected void startPluginActivity(Intent intent) {
   
   
        intent.putExtra(LoadUtil.INTENT_LOAD_PLUGIN, true);
        startActivity(intent);
    }
  
}

  • 2.Hook AMS
public class LoadUtil{
   
   

    private static final String TAG = "LoadUtil";

    private final static String INTENT_ORIGIN_INTENT = "intent_origin_intent";
    private final static String METHOD_START_ACTIVITY = "startActivity";
    public final static String INTENT_LOAD_PLUGIN = "intent_load_plugin";

    public final static int WHAT_LAUNCH_ACTIVITY = 100;
    //9.0版本H 处理启动activity的流程
    public final static int WHAT_EXECUTE_TRANSACTION = 159;

    /**
     * Hook AMS 的startActivity,用ProxyActivity替换plugin 的Activity,以欺骗AMS的manifest校验
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    @SuppressLint("PrivateApi")
    public static void hookAMS() {
   
   
        try {
   
   
            //- 获取singleton(它作为单例持有了IActivityManager实例)
            Field singletonFiled;
            //8.0
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
   
   
                Class<?> clazz = Class.forName("android.app.ActivityManagerNative");
                singletonFiled 
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值