适配 Android P之非SDK接口限制的排查方法
code小生,一个专注 Android 领域的技术平台
公众号回复 Android 加入我的安卓技术群
作者:天才木木链接:https://www.jianshu.com/p/efe6690b36b6声明:本文已获
天才木木
授权发表,转发等请联系原作者授权
0. 结论
从 Android 9(API 级别 28)开始,系统会限制APP通过反射或JNI调用非Andorid SDK的接口。
项目的业务代码可以通过全局搜索检查非SDK接口的使用情况。
几乎所有第三方SDK(包括Android support库!!)都有大量通过反射调用非SDK api的情况。通常反射调用时都有try-catch,能够保证应用不崩,但实际功能受影响的程度无法评估。
官方文档链接:
1. 为什么要限制?
目前,开发者对于非SDK API的调用,一般是采取反射或JNI间接调用的方法进行的。由于Android是开源的,所以开发者对非公有SDK的调用十分混乱,Google为了进一步防止碎片化,规范开发者的API使用行为,于是开始限制开发者通过反射或JNI间接调用非Android SDK提供的api。
这个变更会影响所有运行在9.0及以上的Android系统的APP,无论该APP是否已经升级了Target SDK。
2. 怎么限制?
起初Android9.0发布时,谷歌为非SDK接口制定了白名单(whitelist)、灰名单(greylist)、黑名单(blacklist)。
whitelist,白名单内的api可以正常被调用。
greylist,灰名单的api可以被调用,但未来更高的TargetSDK版本可能会将其列入黑名单。
blacklist,黑名单的api的调用在运行时会抛出异常,如果没有进行处理,将导致APP的Crash,即使进行了try-catch,这些反射的函数/变量也无成功被调用。
后面Android 10.0发布后,非SDK接口的划分变成了:
greylist 无限制,可以正常使用。
blacklist 无论什么版本的手机系统,使用这些api,系统将会抛出错误。
greylist-max-o 受限制的灰名单。APP运行在 版本<=8.0的系统里 可以正常访问,targetSDK>8.0且运行在>8.0的手机会抛出异常。
greylist-max-p 受限制的灰名单。APP运行在 版本<=9.0的系统里 可以正常访问,targetSDK>9.0且运行在>9.0的手机会抛出异常。
下表说明了当您的应用尝试访问黑名单或者在高版本手机上访问受限制的灰名单中的非 SDK 接口时可能会出现的异常:
3. 怎么检测出非SDK接口的使用?
先前去官网下载veridex工具包。
3.1 veridex 工具扫描 APK
自动但不太准确,使用veridex 工具扫描 APK 的整个代码库(包括所有第三方库),并在结果中列举出发现的所有使用非 SDK 接口的行为。这个方法非常方便,但由于扫描范围覆盖项目依赖的第三方库,出来的结果可能比较庞大(甚至有几百个处于黑/灰名单的非SDK 接口调用,其中还有不少误判。
具体方法:
./appcompat.sh --dex-file=app-debug.apk >>result.txt
脚本里可以带上 --imprecise(不精确的),扫描出来的hidden api调用会很多,但是也包含了很多误判。
./appcompat.sh --dex-file=app-debug.apk --imprecise >>result.txt
扫描结果的示例如下:
#51: Reflection greylist-max-o Landroid/animation/TimeAnimator;->mListener potential use(s):Landroid/support/v4/app/FragmentManagerImpl;->getAnimationListener(Landroid/view/animation/Animation;)Landroid/view/animation/Animation$AnimationListener;
#94: Reflection greylist Lcom/android/internal/R$dimen;->status_bar_height use(s):Lcom/demo/common/utils/SystemUtils;->getStatusBarHeight(Landroid/app/Activity;)I
#1340: Reflection blacklist Lcom/android/org/conscrypt/SSLParametersImpl;->setApplicationProtocols potential use(s):Lokhttp3/internal/platform/Jdk9Platform;->buildIfSupported()Lokhttp3/internal/platform/Jdk9Platform;107 hidden API(s) used: 24 linked against, 83 through reflection91 in greylist0 in blacklist1 in greylist-max-o15 in greylist-max-p
use(s)
:左边是被调用的非SDK的api,并非常详细地列出了包名、类名、函数名(or变量名),以及其所属的名单级别(greylist or blacklist)。use(s)
:右边就是调用了非SDK api的项目代码的位置。
比如上面扫描结果告诉我们:
#51
:谷歌的Android-support库中的FragmentManagerImpl通过反射调用了greylist-max-o灰名单中的android/animation/TimeAnimator的mListener变量。#94
:项目里的demo/common/utils/SystemUtils的getStatusBarHeight方法 通过反射获取了com.android.internal.R$dimen类中的status_bar_height变量,属于通过反射调用灰名单的非SDK api,暂时是没有问题。#1340
:项目里的okhttp3/internal/platform/Jdk9Platform的buildIfSupported方法通过反射调用了com/android/org/conscrypt/SSLParametersImpl的setApplicationProtocols方法,属于通过反射调用黑名单里的非SDK api。
实践
最终我在项目里跑脚本./appcompat.sh --dex-file=app-debug.apk --imprecise得出的结果是:
1900 hidden API(s) used: 24 linked against, 1876 through reflection
仔细阅读过扫描结果后可以发现,几乎所有第三方SDK(包括Android support库!!)都有大量通过反射调用非SDK api的情况。通常反射调用时都有try-catch,能够保证应用不崩,但实际功能受影响的程度无法评估。
所以对第三方库的适配方法是查看官网更新日志,并对第三方库进行升级。比如高德地图官网更新日志显示已经适配Android P&Q。
3.2 全局搜索业务代码
手动但比较准确,上述的veridex扫描虽然很快捷,但是输出结果包含了第三方库对非SDK接口的使用情况,对于一般项目来说绝大部分非SDK接口的调用都在第三方库上,在veridex扫描结果中排查项目业务代码对非SDK接口的调用情况比较困难。所以可以通过最原始的办法————全局搜索 JAVA反射相关的api(搜索上面的表格里的getField、getMethod等关键字),与官方给出的hidden api list(上面提到的hiddenapi-flags.csv)做比对,就很容易排查中业务代码里对非SDK接口的调用情况。
上图全局搜索getField,发现项目通过反射获取了Toast类中的mTN成员变量,在官方提供的hiddenapi-flags.csv中可以发现该成员变量是非SDK接口,且属于greylist-max-p受限制的灰名单。即这个反射可以在 版本<=9.0的系统里正常获取到mTN变量,但在targetSDK>9.0且运行在>9.0的手机会抛出异常,由于业务代码对反射调用进行了try-catch,所以实际业务中拿到的是一个null,这个时候我们就可以真切地感受到谷歌官方对非SDK接口的限制,并评估具体的业务影响。
4 总结
以上就是我们在对项目适配Android9.0的过程中,如何应用谷歌针对非SDK接口的限制的排查方法。
谷歌官方的建议有点扯淡:
如果您的应用依赖于非 SDK 接口,则应该开始计划迁移到 SDK 接口或其他替代方案。如果您无法为应用中的功能找到使用非 SDK 接口的替代方案,可以向谷歌官方申请新的公共 API。
网上也有总结了一些绕开非SDK接口限制的方法,可以参考https://juejin.im/post/5ba0f3f7e51d450e6f2e39e0?utm_source=gold_browser_extension
推荐阅读
Android SDK开发与使用的那些事儿
Android P 网络请求相关总结
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
适配 Android P之非SDK接口限制的排查方法相关推荐
- Android P (4)一种绕过Android P上非SDK接口限制的简单方法
一种绕过Android P上非SDK接口限制的简单方法 众所周知,Android P 引入了 针对非 SDK 接口(俗称为隐藏API)的使用限制.这是继 Android N上 针对 NDK 中私有库的 ...
- 一种绕过Android P对非SDK接口限制的简单方法
众所周知,Android P 引入了针对非 SDK 接口(俗称为隐藏API)的使用限制.这是继 Android N上针对 NDK 中私有库的链接限制之后的又一次重大调整.从今以后,不论是native层 ...
- Android 9 的非 SDK 接口限制 | 中文教学视频
我们一直致力于为 Android 用户和开发者提供稳定的体验.秉持这种理念,我们逐步限制应用使用非公开接口,因为这种做法往往导致用户遭遇系统崩溃及开发者需要紧急发布修复的风险.在 Android 8. ...
- Android P版本非SDK接口管控特性,参考华为
Android P版本非SDK接口管控特性解读及适配指导 在Android P版本中,谷歌加入了非SDK接口使用限制,无论是通过调用.反射还是JNI等方式,开发者都无法对非SDK接口进行访问,此接口的 ...
- Android 开发---对非SDK接口限制的适配
前言 项目升级到Android Pie(9),需要考虑适配问题.在此做个总结. Android 9 增加了对非SDK接口访问的限制,无论你是直接访问还是通过反射,JNI等间接访问,都是会被限制的. S ...
- Android P 访问非SDK 接口
Android P 如何访问非SDK 接口 为什么要访问非SDK 接口? 为了让应用能获得更多的系统属性.资源,扩展功能等. 在Android P 之前,我们可以使用反射来访问系统内部分 hide/p ...
- Android 非 SDK 接口常见问题
常规问题 Q1: 什么是非 SDK 接口? A:非 SDK 接口指不在官方Android SDK涵盖范围内的 Java 字段和方法.此类接口是 SDK 的内部实现细节,可能随时会被修改,且不对开发者另 ...
- Android P非SDK接口限制
写在前头 Android Pie(API 28)开始对非SDK接口的使用开始做了限制.只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,就会被限制.这些限制旨在帮助提升用户体验和开发 ...
- android sdk 9.0下载地址,Android9.0对非 SDK 接口的限制
Android9.0对非 SDK 接口的限制 发布时间:2018-10-19 12:00, 浏览次数:919 , 标签: Android SDK 在 Android 9.0 版本中,谷歌加入了非 SD ...
最新文章
- python 栈实现 加减乘除_数据结构与算法(六):基于栈实现简单的四则运算
- 啧啧,这种程序员……| 每日趣闻
- 使用diskpart命令进行扩充硬盘空间操作说明
- 聊天机器人有了长期记忆,遇到不懂的还能上网搜索,网友:像极了不懂装懂时偷偷百度的我...
- 大型网站演化发展历程
- 6.5 scp:远程文件复制
- 修改 Angular Component 构造函数参数被认为是 breaking change
- GNN在谱域下的演化:Spectral CNN,ChebyNet,GCN
- JavaScript 隐性类型转换步骤浅析
- netfilter 和 iptables
- ROS教程之使用UVC摄像头
- extern “C“的作用及理解
- 3DLut表实现log视频的后期调色原理
- CAM和GradCAM
- 微软服务器无法删除不了,[图]Edge无法卸载 引发诸多用户强烈不满
- 状态空间描述到传递函数
- 企业服务总线架构介绍
- Redy语法分析--抽象语法树简介
- 一文解释电路中常用电子元器件应用和选型01
- 2019Android高级面试题总结
热门文章
- 深度学习环境配置——查看显卡信息和对应NVDIA驱动
- 小伙用C++技术实现3D俄罗斯方块游戏,3D元素让人耳目一新
- 扫描电镜下的人体感官结构,超震撼
- 嵌入式C语言学习第三天
- oracle存储过程不退出,oracle 存储过程不结束
- 计算机网络的总体认知——互联网
- 先有鸿钧后有天,陆压道君还在前
- thinkph5.1 简单自定义的日志写入方法
- 从零开始学五线谱_从零开始学乐理|第1课:不认识五线谱?花十分钟就够了...
- 如何去除discuz X2论坛网址中的forum.php