在VirtualApk中 对系统隐藏API的调用采用了反射+Stub两种方式
反射这个大家都比较好理解了
比如说在对资源进行Hook时 我们可以自己生成一个Resources 并使用反射的方式替换Context的mResources
重点学习下Stub
在android中为了保护一些系统API 或者基于其他考虑,一些核心类是被标注为hide 的,这样我们就无法访问这些类,
比如ActivityThread
看过Activity启动流程的同学都知道 ActivityThread 在整个流程中的作用
在VirtualApk中,我们要对Activity进行插件化启动,就要破解Activity启动时的配置文件校验,这部分校验的代码写在
Instrumentation 里面 , 而Instrumentation 是ActivityThread 内包含的一个对象
因此我们要从ActivityThread中拿到Instrumentation 对象进行动态代理的修改绕过这个校验
ActivityThread有一个getInstrumentation()方法,可ActivityThread是hide的
于是可以这么做:
1:新建包android.app(这个其实就是框架中ActivityThread所属的包名)
2:android.app包下面新建类ActivityThread
3:ActivityThread中添加方法
public Instrumentation getInstrumentation() {
throw new RuntimeException("Stub!");
}
注意这个方法的方法体部分
然后就可以访问ActivityThread了
总结:
1:采用Stub这种方式,实际是方便代码编译通过,在实际运行的时候是由rom中的类替代的
2:这种方式理论上是比反射的效率更高的(VirtualApk的注释里面也提到了这一点)
3:这种类只能做为一个载体使用,不能擅自实例化出对象进行调用。脱离框架之后可能就失去作用了
4:这种方式貌似只能对hide的类可以使用,对hide的方法也可以使用
5:AndroidStudio中新建项目依赖使用的android.jar 其实也是由大量的这种Stub类组成的,提供了API调用,编译支持
见下图