要了解插件化首先要具备三个前提条件:
-
Android 系统源码阅读与理解
-
Java 反射机制
-
Hook 技术
什么是Hook
?
在事件执行的过程中截获并监控事件的执行流,将自身的代码融入其执行流中。
Hook介绍: blog.csdn.net/qq_39731011…
案例1:通过hook方式拦截View的onClick()事件加入自己的逻辑;
关键点:
- 替换(把系统中的 替换成 动态代理)
- 动态代理(做我们自己的业务逻辑)
利用动态代理,生成OnClickListener接口代理
,在代理回调中,加入自己的逻辑,然后通过反射,将OnClickListener接口代理替换ListenerInfo
中的mOnClickListener
案例2:通过hook方式启动未注册的Activity:
关键点:
- 通过hook方式,绕过 AMS 检查,在执行 AMS 之前,替换在AndroidManifest.xml里面配置的Activity;
- 通过hook方式,hook launchActivity() 方法,准备实例化AndroidManifest.xml里面配置的Activity的时候,将在AndroidManifest.xml里面配置的Activity,替换成未注册的Activity(给mH(Handler)设置 Callback,在 Callback 中做替换逻辑);
案例3:宿主 跳转 插件里面的Activity
直接跳转的话,一定会报错:
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.netease.plugin_package.PluginActivity" on path:
DexPathList[[zip file "/data/app/com.netease.hookproject-1/base.apk",...... ]]
分析错误原因,来学习Android类加载:
startActivity --> AMS --> ActivityThread(把代理的Activity给换回来了) --> 要去实例化Activity (报错)
Activity --> Instrumentation --> AMS检查 -->
ActivityThread (即将加载)-(handleLaunchActivity 类加载Activity performLaunchActivity --> newActivity(cl == PathClassLoader))
分析Android中的ClassLoader:
1.java中的ClassLoader 和 Android的ClassLoader 是不一样
2.ClassLoader == PathClassLoader
3.PathClassLoader == cl.loadClass(className).newInstance();
PathClassLoader.loadClass --> BaseDexClassLoader -->ClassLoader.loadClass--findClass(空方法) 让覆盖的子类方法去完成 -->
BaseDexClassLoader.findClass() --> pathList.findClass
BaseDexClassLoader.findClass() --> c 为什么为null,--> DexPathList.findClass(className) --> DexFile.loadClassBinaryName(系列步骤后 NDK)
for遍历 dexElements == Element[] ,分析 Element 是什么 ,为什么 Element.dexFile == null?
Android虚拟机 apk中的dex文件相当于Element,Element是dex表现形式的描述 --> Element 中的 dexFile 拥有可执行
为什么 Element == null?
答:因为类加载机制加载的是 宿主的 classes.dex,也就是Elements,没有插件的Element
解决方案:把插件的 dexElements 和 宿主中的 dexElements 融为一体,PathClassLoader 就能加载到 插件/宿主 中的class
Hook式 插件化,就是这么一回事!
补充1:Android ClassLoader介绍
1.java中的ClassLoader 和 Android的ClassLoader 是不一样
2.Android中的ClassLoader 分为两类:
- 系统提供的ClassLoader --> BootClassLoader(给系统预加载使用),PathClassLoader(给程序/系统程序/应用程序 加载class),DexClassLoader(加载 apk文件)
- 自定义ClassLoader
补充2:Android 系统启动流程
- 内核启动 ...
- Init 进程:第一个系统进程
- Init 进程启动 Zygote 进程:ZygoteInit.java --> preload() --> preloadClasses() --> BootClassLoader.getInstance() 实例化
BootClassLoader
; handleSystemServerProcess () --> PathClassLoaderFactory.createSystemServerClassloader() 实例化PathClassLoader
- zygote 进程孵化 SystemServer
- SystemServer 启动很多的服务:AMS、PSM、...
了解到这些后,下一步:将插件的dexElements 和 宿主中的 dexElements 融为一体