适配 非SDK管控(Hidden API)

非SDK管控(Hidden API)

背景

从 Android 9(API 级别 28)开始,此平台对应用能使用的非 SDK 接口实施了限制。只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,这些限制就适用。这些限制旨在帮助提升用户体验和开发者体验,为用户降低应用发生崩溃的风险,同时为开发者降低紧急发布的风险。

在Android Q中,谷歌继续加强了对非SDK接口的使用限制,黑名单接口数量大幅增长,部分非SDK接口被删除,将导致大面积应用无法正常使用的问题,需要开发者重点关注并进行适配。

 

SDK 接口和非 SDK 接口

SDK接口: 谷歌官方网站能查到的接口都是SDK接口 查询链接

非SDK接口: 除了谷歌开放的SDK接口之外的其他JAVA接口都是非SDK接口。

 

滥用非SDK接口的危害

非SDK接口在Android不同版本间存在很大的差异,使用非SDK接口容易带来兼容性问题。

 

名单类型说明

名单 名单类型 说明
黑名单 blacklist 无法调用。无论您应用的目标 API 级别是什么,您都无法使用此列表中的非 SDK 接口。如果您的应用尝试访问其中任何一个接口,系统就会抛出错误。
灰名单 greylist targetSDK>=P时,警告。如果您应用的目标 API 级别较低,您可以访问灰名单中的受限 API。但如果您的应用尝试访问在您的目标 API 级别受限的非 SDK 接口,系统就会假定此 API 已列入黑名单。
  greylist-max-o targetSDK=P时,不允许调用
  greylist-max-p targetSDK=Q时,不允许调用
白名单   此列表中的接口已在 Android 框架软件包索引中正式记录,它们是受支持的接口,您可以自由使用。

 

访问受限的非 SDK 接口时可能会出现的预期行为

访问方式 结果
Dalvik 指令引用某个字段 抛出 NoSuchFieldError
Dalvik 指令引用某个方法 抛出 NoSuchMethodError
通过 Class.getDeclaredField() 或 Class.getField() 进行反射 抛出 NoSuchFieldException
通过 Class.getDeclaredMethod()Class.getMethod() 进行反射 抛出 NoSuchMethodException
通过 Class.getDeclaredFields()Class.getFields() 进行反射 结果中未获取到非 SDK 成员
通过 Class.getDeclaredMethods()Class.getMethods() 进行反射 结果中未获取到非 SDK 成员
通过 env->GetFieldID() 进行 JNI 调用 返回 NULL,抛出 NoSuchFieldError
通过 env->GetMethodID() 进行 JNI 调用 返回 NULL,抛出 NoSuchMethodError

结果为 抛出异常,或者未获取到对象。可通过try catch、判空避免。

 

检测应用非SDK接口列表(建议两个方法并用)

方法1:通过谷歌提供的veridex静态扫描工具获取

veridex 静态扫描工具 下载链接。使用说明请查看压缩包中README.txt文件。

veridex 工具存在以下局限性:

  • 它无法检测到通过 JNI 实现的调用。

  • 它只能检测到一部分通过反射实现的调用。

  • 它对非活动代码路径的分析仅限于 API 级别的检查。

方法2:通过扫描分析动态运行日志获取

关键日志:

Accessing hidden fieldLandroid/os/Message;->flags:I (greylist, JNI)

调试命令:

在Android Q中,启用对非SDK接口的访问的命令已更改,开发者需要通过更改API强制策略来启用对开发设备上的非SDK接口的访问,ADB命令如下:

adb shell settings put globalhidden_api_policy 1

API强制策略中的整数值可以设置为以下三个选项:

  0:禁用所有非SDK接口检测。使用此设置会禁用非SDK接口使用的所有日志消息,并阻止您使用StrictMode API测试应用程序。 

 1:允许访问所有非SDK接口,但打印日志消息,并显示任何非SDK接口使用情况的警告,使用此设置还允许您使用StrictMode API测试您的应用程序。

  2:禁止使用属于黑名单的非SDK接口或目标API级别的受限制灰名单。 

 建议开发者将数值设置为1,再通过自动化或人工测试遍历应用所有功能和界面,然后通过抓取的日志分析调用的非SDK接口。 

 如需将API强制策略重置,可以使用以下命令进行设置: adb shell settings deleteglobal hidden_api_policy

你可能感兴趣的:(android)