Q 行为变更:以 Android Q 为目标平台的应用

非 SDK 接口限制

非SDK接口限制在Android P中就已提出,但是在Q中,被限制的接口的分类有较大变化。

非SDK接口介绍

为了确保应用稳定性和兼容性,Android 平台开始限制您的应用可在 Android 9(API 级别 28)中使用哪些非 SDK 接口。Android Q 包含更新后的受限非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。

非SDK接口限制就是某些SDK中的私用方法,如private方法,你通过Java反射等方法获取并调用了。那么这些调用将在target>=P或target>=Q的设备上被限制使用,当你使用了这些方法后,会报错:

获取方法

报错信息

 

 

Dalvik instruction referencing a field

NoSuchFieldError thrown

Dalvik instruction referencing a method

NoSuchMethodError thrown

Reflection via Class.getDeclaredField() or Class.getField()

NoSuchFieldException thrown

Reflection via Class.getDeclaredMethod(), Class.getMethod()

NoSuchMethodException thrown

Reflection via Class.getDeclaredFields(), Class.getFields()

Non-SDK members not in results

Reflection via Class.getDeclaredMethods(), Class.getMethods()

Non-SDK members not in results

JNI via env->GetFieldID()

NULL returned, NoSuchFieldError thrown

JNI via env->GetMethodID()

NULL returned, NoSuchMethodError thrown

非SDK接口查找

如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用进行确认。

当你调用了非SDK接口时,会有类似Accessing hidden XXX的日志:

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
但是一个大项目到底哪里使用了这些方法,靠review代码和看日志肯定是不现实的,谷歌官方也提供了官方检查器veridex用来检测一个apk中哪里使用了非SDK接口。veridex下载。

https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat

其中有windows,linux和mac版本,对应下载即可。

下载解压后命令行cd到veridex目录下使用./appcompat.sh --dex-file=Q.apk即可自动扫描。Q.apk为包的绝对路径,如果包与veridex在相同目录下直接输入包文件名即可。

扫描结果分为两部分,一部分为被调用的非SDK接口的位置,另一部分为非SDK接口数量统计,例如:

 

greylist: 灰名单,即当前版本仍能使用的非SDK接口,但在下一版本中可能变成被限制的非SDK接口
blacklist:黑名单,使用了就会报错。也是我们项目中必须解决的非SDK接口
greylist-max-o:在targetSDK<=O中能使用,但是在targetSDK>=P中被限制的非SDK接口
greylist-max-p:在targetSDK<=P中能使用,但是在targetSDK>=Q中被限制的非SDK接口
所以从适配Q的角度出发,除了greylist我们可以暂时不解决以外,其余三种类型的非SDK接口需要我们进行适配。

非SDK接口适配

如果您的应用依赖于非 SDK 接口,则应该开始计划迁移到 SDK 替代方案。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,则应该请求新的公共 API。

官方要求targetSDK>=P的应用不使用这些方法,并寻找其他的公共API去替代这些非SDK接口,如果找不到,则可以向谷歌申请,请求一个新的公共API https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces#feature-request (一般不需要)。(http://www.amjmh.com)

就我个人扫描并定位的结果来看,项目中使用非SDK接口大概率有以下两种情况:

在自定义View的过程中为了方便,使用反射修改某个参数。
三方SDK中使用了非SDK接口(这种情况比较多)。
第一种是好解决的,毕竟是我们自己写的代码。

第二种就头疼了,只能更新到最新的三方SDK版本,或者提工单、换库(也是整个适配过程中工作量最庞大的部分)。

posted @ 2019-09-17 17:53  李艳艳665  阅读(259)  评论(0编辑  收藏  举报