Android之隐藏api介绍
..
Android P 引入了针对非 SDK 接口(俗称为隐藏API)的使用限制。这是继 Android N上针对 NDK 中私有库的链接限制之后的又一次重大调整。
从今以后,不论是native层的NDK还是 Java层的SDK,我们只能使用Google提供的、公开的标准接口。这对开发者以及用户乃至整个Android生态,当然是一件好事。
但这也同时意味着Android上的各种黑科技有可能会逐渐走向消亡。
公共 SDK 接口是在 Android 框架软件包索引 中记录的那些接口
从 Android Pie 开始,对某些隐藏类、方法和字段的访问受到限制在 Pie 之前,通过简单地使用反射来使用这些隐藏的非 SDK 组件非常容易。
但是,现在当尝试访问时,面向 API 28 (Pie) 或更高版本的应用程序将遇到 ClassNotFoundException、NoSuchMethodError 或 NoSuchFieldException Activity#createDialog() 。
先来看看系统是如何实现这个限制的。
通过反射或者JNI访问非公开接口时会触发警告/异常等,那么不妨跟踪一下反射的流程,看看系统到底在哪一步做的限制。
先来看一下 java.lang.Class.getDeclaredMethod(String) :
其中看一下 ShouldBlockAccessToMember 的调用,如果它返回false,那么直接返回 nullptr ,上层就会抛 NoSuchMethodXXX 异常;也就触发系统的限制了。
源码如下:
继续跟踪下 GetMemberAction方法 :
继续跟踪GetMemberActionImpl方法:
其中调用到了
只要 IsExempted 方法返回 true,就算这个方法在黑名单中,依然会被放行然后允许被调用。
IsExempted 方法:
继续跟踪传递进来的参数 runtime->GetHiddenApiExemptions() 发现也是 runtime 里面的一个参数.
这样就可以直接修改 hidden_api_exemptions_ 绕过去限制。
Java 层的,有一个对应的 VMRuntime.setHiddenApiExemptions 方法,通过 VMRuntime.setHiddenApiExemptions 设置下豁免条件,就能愉快滴使用反射了。
IsExempted 方法里面调用 DoesPrefixMatch 方法。DoesPrefixMatch是对方法签名进行前缀匹配。所有Java方法类的签名都是以 L 开头,这样就可以直接传个 L 进去,所有的隐藏API全部被赦免了!
另一种绕过 Android P以上非公开API限制的办法