如何面对Android P的限制
写作这本书的时候,Google推出了Android P preview的操作系统,会限制对@hide api的反射调用。目前会通过log发出警告,用户代码仍然能够获取到正确的Method或Field,在后续版本中获取到的Method或Field极有可能为空。
但是道高一尺,魔高一丈。Google对这次限制,很快就被技术极客们绕过去了,有两种解决方法:
1)把通过反射调用的系统内部类改为直接调用。具体操作办法是,在Android项目中新建一个库,把要反射的类的方法和字段复制一份到这个库中,App对这个库的引用关系设置为provided。那么我们就可以在App中直接调用这个类和方法,同时,在编译的时候,又不会把这些类包含到apk中。
其实早在2015年,hoxkx就在他的插件化框架中实现了这种技术。但是这种解决方案,仅限于Android系统中标记为public的方法和字段,对于protected和private就无能为力了。比如AssetsManager的addAssetPath方法,ActivityThread的currentActivityThread方法。
2)类的每个方法和字段都有一个标记,表明它是不是hide类型的。我们只要在jni层,把这个标记改为不是hide的,就可以绕过检查了。
然而,魔高一丈,道高一丈二。Google在Android P的正式版中势必会推出更严厉的限制方案,到时候,又会有新的解决方案面世,让我们拭目以待。
其实,开发者是无意和Google进行技术对抗的,这是毫无意义的。泛滥成灾的修改导致了App大量的崩溃,Google实在看不下去了,所以才搞出这套限制方案;另一方面,插件化技术是刚需,尤其在中国的互联网行业,App崩溃会直接影响使用,很可能导致经济损失,所以开发者才会不惜一切代价走插件化这条路。
再回到限制方案来,Google也不是清一色不要开发者使用系统底层的标记为hide的API,而是推出了一组黑灰名单,如下所示:
所以,另一种应对策略是,在插件化中使用浅灰名单中的API,比如说ActivityThread的currentActivityThread方法。
Google的这组清单还在持续调整中,据我所知,给各大手机厂商的清单与其在社区中发布的清单略有出入。在Android P的正式版本中,这份清单会最终确定下来。所以现在中国的各个插件化框架的开发人员,都在等Android P的正式版本发布后再制定相应的策略。留给中国队的时间不多了。