Android修炼之检测非SDK接口

栏目: Android · 发布时间: 5年前

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

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

区分SDK接口和非SDK接口

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

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

  1. 白名单:自然就是可以直接使用的SDK接口;
  2. 浅灰名单:仍可以访问的非 SDK 函数/字段;
  3. 深灰名单:包含我们在开发期间未看到使用,但是我们可能已经忽视的函数/字段。列入深灰名单的函数/字段是那些与SDK和浅灰名单中的公开接口紧密相关的函数/字段。
    • 对于目标SDK低于API级别28的应用,允许使用深灰名单接口;
    • 对于目标SDK为API 28或更高级别的应用:行为与黑名单相同;
  4. 黑名单:受限,无论目标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时,出现过这种对话框提示:

Android修炼之检测非SDK接口

引发异常

官方说明:

Android修炼之检测非SDK接口

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

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

Android修炼之检测非SDK接口
Android修炼之检测非SDK接口

使用veridex检测工具

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

Android修炼之检测非SDK接口
可以看到它里面包含了各名单的txt文件,其中 appcompat.sh

就是运行脚本。

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

./appcompat.sh --dex-file=文件名.apk --imprecise
复制代码

结果:

Android修炼之检测非SDK接口

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

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

Android修炼之检测非SDK接口

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

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

Android修炼之检测非SDK接口

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

降维打击

降维打击

杨 健 / 北京时代华文书局 / 2016-10 / 68

“降维打击”出自中国科幻作家刘慈欣的小说《三体》,而笔者在这本书中试图把“降维打击”的思维引入到企业经营管理的实战中,总结出一套“降维打击”的商业理论。 按照笔者的理解,企业竞争力可以体现在若干个维度的累加上,具有高维度思维的企业,主动将竞争对手的某一核心维度的竞争力降为零,并跟对手在自己更具竞争优势的维度内进行竞争,从而实现以小博大、以弱灭强的商业竞争结果,这就是企业竞争中的“降维打击”。......一起来看看 《降维打击》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具