概述
插件化用到代理模式,所以要掌握代理模式。随着泛型引进,代理模式分为动态代理和静态代理,在插件化中分别表现为对 Instrumentation 和 对 AMN 进行Hook。
代理模式的UML图如下:
其中RealSubject 和 Proxy 都是Subject 的子类,在Proxy内部有一个RealSubject类型的成员变量,Proxy 的Reqeust 方法会调用 RealSubject 的Request方法,代码如下;
1 | abstract public class Subject { |
简单的UML图和这短短的代码,就是代理的精髓,在介绍代理模式的使用场景时,就知道它的威力了。
远程代理(AIDL)
在Android系统中,远程代理的设计实现就是AIDL。以之前的例子来说,add 方法把a和b两个整数写入data中,通过mRemote的transact方法,把data和reply发送到AIDL的另一端,replay是回调函数,会把计算结果传递回来,UML图如下所示:
给生活加点料(记日记)
Class1有个doSomething方法,我们想在这个方法之前记录一行日志,一般的做法是,直接在在doSomething 方法的最前端写一行代码用于记录日志,在学习了代理模式后,我们可以设计一个Class1Proxy,代码如下:
1 | public class Class1Proxy implements Class1Interface { |
静态代理和动态代理
前面讲的是“静态代理”,但是其实这样是有问题的,每个类都要有个对应的Proxy类,Proxy类的数量会很多,但其实它们的逻辑大同小异。接下来介绍“动态代理”,基于 Proxy 类的 newProxyInstance 方法,它的声明如下:
static Object newProxyInstance(ClassLoder loader, Class<?>[] interfaces, InvocationHandler h)
其中,interfaces 设置为目标对象Class1 所实现的接口类型,对应上面的例子是 Class1Interface,我们通过h对象,可以实现把目标对象 class1 注入,我们看下在实际应用中自己实现的这个h:
1 | public class InvocationHandlerTest implements InvocationHandler { |
注意 method.invoke(target,objects),其中target 就是 class1 对象,接下来调用就是如下方式:
1 | Class1Interface proxy = new Class1(); |
所以,invoke方法实际上就是在执行 class1 的doSomething 方法。
对AMN的Hook
后续有时间补上
对PMS的Hook
PMS 是系统服务,是没办法Hook的,这个标题只是为了容易理解。我们只能修改它在Android App 进程中的代理对象,它是PackageManager 类型的在很多类中都有这个代理的对象,比如,在ActivityThread 中,有一个字段 sPackageManager ,以及 ApplicationPackageManager 的 mPM字段,我们可以尝试Hook这些字段。
代码:略,后续补上。