Android修煉之檢測非SDK接口

前言

上篇文章Android修煉之Pie 適配的搬運工中介紹了Android P的一些行爲變動並提供了一些對齊劉海和非SDK接口的適配建議,大部分人仍是更加關心非SDK接口的問題,因此本文來講一下如何檢測非SDK接口。java

區分SDK接口和非SDK接口

通常來講,SDK接口是指在Android框架軟件包索引中記錄的接口,其對立面天然就叫非SDK接口了。Android 9引入了針對非SDK接口的使用限制,不管是直接使用仍是經過反射或JNI間接使用。這意味着,經過反射之類的語義來操做某個類時,不該訪問SDK中未列出的函數或字段(一般都有@hide標誌)。linux

Android 9將非SDK接口都放在了各名單中:android

  1. 白名單:天然就是能夠直接使用的SDK接口;
  2. 淺灰名單:仍能夠訪問的非 SDK 函數/字段;
  3. 深灰名單:包含咱們在開發期間未看到使用,可是咱們可能已經忽視的函數/字段。列入深灰名單的函數/字段是那些與SDK和淺灰名單中的公開接口緊密相關的函數/字段。
    • 對於目標SDK低於API級別28的應用,容許使用深灰名單接口;
    • 對於目標SDK爲API 28或更高級別的應用:行爲與黑名單相同;
  4. 黑名單:受限,不管目標SDK如何。平臺將表現爲彷佛接口並不存在。

這些名單均可以在:非SDK接口名單中找到。若是不想編譯AOSP,能夠直接下載該頁的tgz文件,解壓便可看到對應的txt文件。git

如何檢測非SDK接口?

查看logcat日誌

在Android 9的系統中,如你的應用中使用了非SDK接口,系統將會在APP運行時打印日誌;若是訪問了某些「列入灰名單的」非SDK接口,系統還可能顯示Toast;若是訪問了「列入黑名單的」非SDK接口,系統將引起異常。github

日誌消息微信

在開發過程當中,咱們能夠經過AS的logcat來查看日誌,不然就是經過adb logcat了。非SDK接口的日誌會顯示在正在運行的應用的PID下,大概格式是:app

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();
        }
    }
複製代碼

他們的日誌以下:ide

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時,出現過這種對話框提示:

Dialog提示

引起異常

官方說明:

非SDK接口引起後果

經測試,只有深灰名單黑名單中的非SDK接口會引起異常和錯誤。

注意:當TargetSDK>=28時,深灰名單和黑名單都會引起異常;而當TargetSDK<28時,只有黑名單會引起異常。示例結果以下:

深灰名單引起異常

黑名單引起異常

使用veridex檢測工具

谷歌提供了一個靜態檢測工具:veridex,能夠幫助咱們檢測apk中是否使用了非SDK接口。這裏使用veridex-linux.zip進行測試,解壓後目錄結構以下:

veridex
能夠看到它裏面包含了各名單的txt文件,其中 appcompat.sh就是運行腳本。

將待檢測的apk文件拷貝到veridex目錄下,運行如下命令便可:

./appcompat.sh --dex-file=文件名.apk --imprecise
複製代碼

結果:

示例檢測結果
這裏顯示的數量明顯比咱們示例中的多,這是爲何?觀察詳細內容,發現veridex把Android本身調用的也檢測出來了。

若是去掉--imprecise會檢測不出來黑名單的接口。

示例檢測結果2
咱們能夠經過重定向將日誌保存在文件中,再進行細緻的分析。

咱們主要關注黑名單和深灰名單。能夠看到,日誌中給出了調用非SDK接口的位置,很容易定位。

定位問題

總結

  1. 在開發過程當中能夠經過日誌查看是否調用了非SDK接口;
  2. 主要注意深灰名單和黑名單的接口調用,雖然程序中常常寫有try catch,但仍是竟可能找到繞過或者替代的方案;
  3. 使用veridex分析apk時,最好帶上--imprecise參數,能夠看到更多詳細的信息;
  4. 示例代碼:github.com/zjxstar/And…

參考資料

  1. 官網
  2. 史上最嚴管控,Android P非SDK接口管控特性解讀及適配
  3. Android P非SDK的隱藏API調用檢測

關注微信公衆號,最新技術乾貨實時推送

image
相關文章
相關標籤/搜索