sdk接口测试 android,Android修炼之检测非SDK接口

上篇文章 Android修炼之Pie 适配的搬运工 中介绍了Android P的一些行为变更并提供了一些对齐刘海和非SDK接口的适配建议,大部分人还是更加关心非SDK接口的问题,所以本文来说一下如何检测非SDK接口。

区分SDK接口和非SDK接口

一般来说,SDK接口是指在 Android 框架软件包索引中记录的接口,其对立面自然就叫非SDK接口了。Android 9引入了针对非SDK接口的使用限制,无论是直接使用还是通过反射或JNI间接使用。这意味着,通过反射之类的语义来操作某个类时,不应访问SDK中未列出的函数或字段(通常都有 @hide 标志)。

Android 9将非SDK接口都放在了各名单中:

白名单:自然就是可以直接使用的SDK接口;

浅灰名单:仍可以访问的非 SDK 函数/字段;

深灰名单:包含我们在开发期间未看到使用,但是我们可能已经忽视的函数/字段。列入深灰名单的函数/字段是那些与SDK和浅灰名单中的公开接口紧密相关的函数/字段。

对于目标SDK低于API级别28的应用,允许使用深灰名单接口;

对于目标SDK为API 28或更高级别的应用:行为与黑名单相同;

黑名单:受限,无论目标SDK如何。平台将表现为似乎接口并不存在。

这些名单都可以在:非SDK接口名单中找到。如果不想编译AOSP,可以直接下载该页的 tgz 文件,解压即可看到对应的 txt 文件。

如何检测非SDK接口?

查看logcat日志

在Android 9的系统中,如你的应用中使用了非SDK接口,系统将会在APP运行时打印日志;如果访问了某些“列入灰名单的”非SDK接口,系统还可能显示Toast;如果访问了“列入黑名单的”非SDK接口,系统将引发异常。

日志消息

在开发过程中,我们可以通过AS的logcat来查看日志,否则就是通过 adb logcat 了。非SDK接口的日志会显示在正在运行的应用的PID下,大概格式是:

Accessing hidden field Landroid/net/wifi/WifiManager;->WIFI_SCAN_AVAILABLE:Ljava/lang/String; (dark greylist, reflection)

复制代码

Accessing hidden:固定格式

field:可能是method,表示调用的是属性还是方法

Landroid/net/wifi/WifiManager:表示调用的类名

->WIFI_SCAN_AVAILABLE:Ljava/lang/String;:表示调用的属性和方法名

(dark greylist, reflection):前半部分表示该非SDK接口在哪个名单中,后半部分表示被调用的方式,比如:reflection(反射)和JNI

这里给出几个示例:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_third);

WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);

Field field = null;

try {

field = wifiManager.getClass().getDeclaredField("WIFI_SCAN_AVAILABLE");

Log.d("ThirdActivity", (String) field.get(wifiManager));

} catch (NoSuchFieldException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

// 直接在浅灰名单中找的接口

public void testLightGreyList(View view) {

ReflectUtils.getMethod(TelephonyManager.class, "isMultiSimEnabled");

}

// 直接在深灰名单中找的接口

@TargetApi(Build.VERSION_CODES.M)

public void testDarkGreyList(View view) {

ReflectUtils.getField(CarrierConfigManager.class, "KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL");

}

// 直接在黑名单中找的接口

public void testBlackList(View view) {

try {

ReflectUtils.getMethod(ReflectUtils.getClass("android.net.util.IpUtils"), "ipChecksum", ByteBuffer.class, int.class);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

复制代码

他们的日志如下:

Accessing hidden field Landroid/net/wifi/WifiManager;->WIFI_SCAN_AVAILABLE:Ljava/lang/String; (dark greylist, reflection)

Accessing hidden method Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z (light greylist, reflection)

Accessing hidden field Landroid/telephony/CarrierConfigManager;->KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL:Ljava/lang/String; (dark greylist, reflection)

Accessing hidden method Landroid/net/util/IpUtils;->ipChecksum(Ljava/nio/ByteBuffer;I)S (blacklist, reflection)

复制代码

注意:在debug的时候,只有触发了对应的调用逻辑,才会打印日志,而不是静态检测。所以新项目中,我们在开发过程中就要注意非SDK接口的调用。

Toast和Dialog提示

可能因为我的模拟器用的是Android P的正式版,去除了Toast提示。所以,在测试的时候并没有看到相关的Toast提示。在预览版中应该有Toast提示功能。当然,也可能是我没有触发“某些灰名单中的非SDK接口”(官方文档原话)的原因。

不过,当我把TargetSDK改为27时,出现过这种对话框提示:

43b3dddfabece08ecee466a335b96c91.png

引发异常

官方说明:

4e9b898db79e1a67fd645c922d46b099.png

经测试,只有 深灰名单 和 黑名单 中的非SDK接口会引发异常和错误。

注意:当TargetSDK>=28时,深灰名单和黑名单都会引发异常;而当TargetSDK<28时,只有黑名单会引发异常。示例结果如下:

f7ccb3f72838e9997f4eb0a6d957f043.png

aa0e2ffec55b88c809d6bdcc58952f52.png

使用veridex检测工具

谷歌提供了一个静态检测工具:veridex,可以帮助我们检测apk中是否使用了非SDK接口。这里使用 veridex-linux.zip 进行测试,解压后目录结构如下:

9cc3d676e257ab9a3fe1a164008d8ae0.png 可以看到它里面包含了各名单的txt文件,其中

appcompat.sh

就是运行脚本。

将待检测的apk文件拷贝到veridex目录下,运行以下命令即可:

./appcompat.sh --dex-file=文件名.apk --imprecise

复制代码

结果:

38472dbaaf907d7600e72683b857d869.png

这里显示的数量明显比我们示例中的多,这是为什么?观察详细内容,发现veridex把Android自己调用的也检测出来了。

如果去掉 --imprecise 会检测不出来黑名单的接口。

0cb4684c275ea1ef713307caa251d4ac.png

我们可以通过重定向将日志保存在文件中,再进行细致的分析。

我们主要关注黑名单和深灰名单。可以看到,日志中给出了调用非SDK接口的位置,很容易定位。

c0e513e0ec4a53f5882c8c3fba2c2be7.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值