这篇文章主要讲了 Android 9.0(Android P)如何限制应用调用内部 API(非 SDK 接口),以及背后的技术原理和影响,用通俗的话总结如下:
一、为什么限制内部 API?
- 兼容性问题:很多 App 偷偷使用 Android 系统未公开的内部 API(标 @hide 的方法 / 字段),但这些接口没被官方支持,Android 大版本升级时可能突然删除或修改,导致 App 崩溃(比如 Android P 升级后大量 App 闪退)。
- Google 的目标:强制 App 使用官方 SDK 接口,让 Android 生态更稳定,避免 “黑科技” 破坏兼容性。
二、限制后的表现:用内部 API 会报错
如果 App 通过反射(如getDeclaredMethod)或 JNI 调用内部 API,会出现以下错误:
- 反射调用:抛出
NoSuchMethodException/NoSuchFieldException; - JNI 调用:返回 NULL,引发崩溃;
- 甚至会弹出 Toast 警告(调试模式下)。
三、限制机制:像 “门禁系统” 一样检查 API 访问
当 App 调用内部 API 时,系统会按以下流程 “安检”:
-
反射 / JNI 调用触发检查:
比如调用Class.getDeclaredMethod()时,最终会走到 native 方法getDeclaredMethodInternal,然后进入检查逻辑ShouldBlockAccessToMember。 -
检查是否 “允许进入”(白名单 / 策略判断) :
- 白名单(kWhitelist) :允许访问,比如系统核心 API;
- 灰名单(Light/Dark Greylist) :根据 “策略严格程度” 决定是否警告或禁止;
- 黑名单(kBlacklist) :直接禁止访问。
-
策略严格程度(EnforcementPolicy) :
kNoChecks:不检查,全允许(测试用);kJustWarn:只警告,不禁止;kDarkGreyAndBlackList:禁止深灰名单和黑名单;kBlacklistOnly:只禁止黑名单(Android P 默认策略)。
-
豁免情况(类似 “VIP 通行证”) :
- 系统 App(用平台密钥签名)、BootClassLoader 加载的类、调试模式下标记为可信任的类,可绕过限制。
四、黑白名单怎么来的?
- 编译时确定:系统编译时,会根据
hiddenapi-force-blacklist.txt等文件,将 API 分类到不同名单,记录在 dex 文件的访问标志中。 - 厂商限制:手机厂商可以往黑名单加自己的 API,但不能删除 Google 的名单,保证兼容性。
五、对开发者的影响和建议
-
不能再用 “黑科技” :
比如插件化、热修复等依赖内部 API 的技术会受影响,需改用官方接口。 -
如何检测?
- 用 AOSP 的
veridex工具扫描 App 是否使用内部 API; - 运行时会打印警告日志(如
Accessing hidden method...)。
- 用 AOSP 的
-
绕过限制的方法(不推荐) :
- 修改系统策略(如设置
EnforcementPolicy为不检查); - 将类加载器换成 BootClassLoader;
- 添加豁免名单(但 Google 在封堵这些漏洞)。
- 修改系统策略(如设置
六、总结
Android P 的内部 API 限制就像给系统加了 “门禁”,强制 App 用官方接口,虽然短期内让插件化等技术变难,但长期看能让 Android 生态更稳定。开发者需避免使用非 SDK 接口,否则升级系统时可能遇到兼容性问题。