AndroidComponentPlugin

Introduction: Android 上简单实现四大组件的插件化,供学习使用
More: Author   ReportBugs   
Tags:

Android 上简单实现四大组件的插件化

说明:

此项目仅用于学习插件化基本的实现思路,在此基础上学习理解四大组件的运行机制。

实现插件化的重点在于对 Android 四大组件和资源加载流程的分析和解读。

插件化代码的编写,涉及到的知识点主要有 java 中的反射,动态代理,静态代理以及 android 中的 AIDL 跨进程通信,binder 机制,ClassLoader 加载机制,四大组件的运行原理等等。

本项目代码主要参考维术插件化系列博客示例代码。在此基础上做了大量的版本适配(android4.0 ~ android10,android R),以及对代码增加了大量的注释。 维术插件化系列博客和示例代码,写的特别好,值得反复学习和思考,在此特别感谢。

万事开头难,学习的过程是辛苦的,对遇到的知识点采用各个击破的方法,对四大组件流程分析文章进行反复的阅读和理解,日积月累,会有所收获。

示例代码适配情况如下:

版本\组件 api Activity Service BroadcastReceiver ContentProvider
androidR R
android29 10.0
android28 9.0
android27 8.1
android26 8.0
android25 7.1.1
android24 7.0
android23 6.0
android22 5.1
android21 5.0
android19 4.4
android18 4.3
android17 4.2
android16 4.1
android15 4.0.3

✅表示测试通过.

本项目特色:

  1. Activity 的插件化,提供了 2 种方式:Hook IActivityManager 和 Hook Instrumentation
  2. 加载插件中的类,提供了 2 种方式去 Hook BaseDexClassLoader
  3. 示例代码均提供详尽的注释,提供插件化入门的基础知识点
  4. 提供方便的调试脚本
  5. 提供了通用的项目 gradle 配置和混淆配置

要彻底搞清楚代码,需要提前掌握的知识点如下:

  1. 反射的使用 1
  2. 反射的使用 2
  3. 泛型
  4. 动态代理
  5. AIDL 通信
  6. Activity 启动流程以及其中涉及到的两次跨进程通信
  7. Handler 消息处理机制

问题思考

  1. 如何确保我们启动的未注册的 Activity,有正常的 Activity 生命周期?

源码探索系列 29---插件化基础之启动插件的 Activity

  1. 从整体宏观的角度看,我们到底做了什么?

  2. 对 PackageManager 的 hook,为什么要 hook 两个地方

hook 技术(三)对 AMS&PMS 进行 Hook

@Override
public PackageManager getPackageManager() {
    if (mPackageManager != null) {
        return mPackageManager;
    }
    IPackageManager pm = ActivityThread.getPackageManager();
    if (pm != null) {
        return (mPackageManager = new ApplicationPackageManager(this, pm));
    }
    return null;
}

由于系统的执行肯定在我们代码之前,所以系统先生成了一个 pm,这个是原生的 pm,然后保存在 ApplicationPackageManager 中, 使得以后使用 ContextImp.getPackageManager()都返回这个 IPackageManager 对象。 就算我们后来替换了 ActivityThread.getPackageManager(),但是也不影响 mPackageManager 里面之前包装好的。 所以我们还需要改变 mPackageManager 里面的原来的 pm 对象。

  1. Hook AMS 和 Hook Instrumentation 两种方式的区别?

  2. 为什么偶尔出现 pre-verified 异常? 这个问题属于 dex 热修复范畴。首先出现这个问题的充分条件: (1) 一个“独善其身”的 A.dex(所有的类引用都在本 dex 内,没有跨 dex 调用) (2) 另一个 B.dex 包含(1)中的某个类 XiaoMing (3) 一个类加载器同时加载了(1)跟(2),查找时(2)优先于(1) 当程序试图调用 XiaoMing 时,在 B 中发现了,但是回头一看 XiaoMing 早已被 A 包养了。遂崩溃。 通常我们并不满足(1)。插件并非独立的,或多或少依赖于宿主包或者公共库,难以“独善其身”,无法被打上 CLASS_ISPREVERIFIED 标签。 当出现这个问题时,请确认在不同的插件中是否引用了同一个第三方库或者其不同版本。

参考文章列表

  1. Android:学习 AIDL,这一篇文章就够了(上)
  2. Android:学习 AIDL,这一篇文章就够了(下)
  3. 大白话说 Java 反射:入门、使用、原理
  4. Hook 机制之动态代理
  5. Android 插件化原理解析——Hook 机制之 Binder Hook
  6. Android 插件化原理解析——Activity 生命周期管理
  7. Android 插件化原理解析——插件加载机制
  8. Android 插件化原理解析——广播的管理
  9. Android 插件化原理解析——Service 的插件化
  10. Android 插件化原理解析——ContentProvider 的插件化
  11. Android 插件化原理解析——Hook 机制之 AMS&PMS
  12. Android 系统篇之----Hook 系统的 AMS 服务实现应用启动的拦截功能
  13. Android 插件化的兼容性(中):Android P 的适配
  14. Android Hook Activity 的几种姿势

License

AndroidComponentPlugin is Apache License 2.0.

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools