涉及到的同系列往期文章:
- Android插件化原理(一)—— 插件类加载、类加载原理、(双亲委托机制)
- StartActivity原理(一)——Android9.0 pauseActivity原理
- StartActivity原理(二)——Android9.0 startActivity原理,Activity启动原理
- 再论Handler—Handler事件分发、Handler线程切换原理解析
本篇文章目录:
1 原理
1.1 涉及到的Framework原理
回顾第一篇Android插件化原理(一)—— 插件类加载、类加载原理、(双亲委托机制)两点:
类加载器
为什么要说ClassLoader呢,因为class 都是由ClassLoader加载的,应用的所有类都在类加载器中。
DexClassLoader8.0之前提供给系统使用,8.0之后与PathClassLoader并无区别PathClassLoader,8.0之前提供给开发者使用,用于加载应用class文件,例如CustomActivity、CustomeFragment,包括三方jar、apk、库的class;8.0之后与DexClassLoader并无区别;BootClassLoader:用于加载Framework的class文件,例如Activity、Fragment
- 加载插件类原理:
- 创建插件的DexClassLoader类加载器,通过反射获取插件的dexElements
- 获取宿主的PathClassLoader类加载器,通过反射获取宿主的dexElements
- 合并宿主的dexElements和插件的dexElements,生成新的Element[]对象
- 通过反射把新的Element[]复制给宿主的dexElements。
以及StartActivity原理(二)——Android9.0 startActivity原理,Activity启动原理提到的
- Activity启动原理:

app进程告知AMS要启动activity,AMS检测Activity存在后,返回目标activity的类信息,并通知app进程构造插件Activity实例;
1.1 核心思想
- 启动插件的activity;
- 检测到启动的是插件Acitivity,将其hook成宿主app的ProxyActivity;
- AMS检测完成后,app启动ProxyActivity时,将其hook成我们的插件Activity。
1.2 具体原理
上面三步虽然简单,但是要明白为什么这么做?这么做原因有两点:
- 目标插件activity不在宿主Manifest清单文件中;
- 启动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

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





