Android 開發---對非SDK介面限制的適配
前言
專案升級到Android Pie(9),需要考慮適配問題.在此做個總結.
Android 9 增加了對非SDK介面訪問的限制,無論你是直接訪問還是通過反射,JNI等間接訪問,都是會被限制的.
SDK介面和非SDK介面有啥區別?
SDK介面是那些官方支援的,Android framework 文件中可以找的.Android framework Package index .那非SDK介面就自然是相反的意思了.
非SDK介面的級別
非SDK介面很對,Google對它按限制程度進行了分類,分為light-greylist(淺灰列表),dark-greylist(深灰列表),blacklist(黑列表).
- 對於light-greylist,非SDK介面的Methods/fields 還可以繼續使用
- 對於dark-greylist,應用的target SDK version 小於28的,非SDK介面還是可以繼續使用的,但是如果target Sdk version 大於等於28的話,就不能用了,會拋exception 如:NoSuchMethodError/NoSuchFieldException.
- 對於blacklist 無論你的target SDK version 是多少,都不能用非SDK介面.否則就會出現異常.
注意
對於light-greylist和dark-greylist,他們都屬於grey,灰色的,雖然現在在Android 9上還可以使用,但是在之後的版本中,不能保證還可不可以繼續用,沒準,現在在grey list裡的下個版本就被Google移到 black list列表裡面了
繼續使用非SDK介面導致的結果
上面其實說的也比較清楚了,就是出現異常.下面的表也描述的更具體點
訪問方式 | 結果 |
---|---|
Dalvik指令 引用一個field | NoSuchFieldError thrown |
Dalvik指令 引用一個method | NoSuchMethodError thrown |
通過Class.getDeclaredField() or Class.getField()反射 | NoSuchFieldException thrown,Non-SDK members not in results |
通過Class.getDeclaredMethod(), Class.getMethod()反射 | NoSuchMethodException thrown,Non-SDK members not in results |
JNI 通過 env->GetFieldID()方式 | NULL returned, NoSuchFieldError thrown |
JNI 通過 env->GetMethodID()方式 | NULL returned, NoSuchMethodError thrown |
非SDK介面列表
上面說說了,有三種非SDK介面列表,如果我們想知道這些列表裡面的具體有哪些內容,可以進入Google提供的列表索引裡去檢視,看看具體是哪些限制的method,field.
定位非SDK介面
-
你可以在Android 9的裝置上面執行你的app,如果你的APP有訪問非SDK介面的話,會打印出相關的log資訊,來幫助你定位,解決非SDK介面問題.log的資訊樣式如下:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
-
Android 9 支援通過使用StrictMode的相應Api來檢測非SDK介面的使用.通過使用detectNonSdkApiUsage 方法來啟用檢測功能,檢測功能的啟用越早啟用越好,官方建議是在application的onCreate方法中呼叫.關於使用這個方法來檢測非SDK介面的呼叫,大家可以自行去原始碼中看該方法的使用,有註釋說明,很容易上手,在此就不再贅述.
-
通過Google提供的檢測分析工具veridex來,檢測非SDK介面的使用情況.veridex的下載地址如下:
veridex download address
我的平臺的是Linux的,所以把veridex-linux.zip 解壓後,cd 進入,使用./appcompat.sh --dex-file = test.apk(apk file location) 命令即可完成檢測.
效果如下:
從veridex下載列表上面只看到了適合Linux平臺的,Mac平臺的veridex壓縮包,沒看到Windows的,網上有看到說Windows平臺的不能用這個工具,但是這邊試了與veridex-linux.zip同級目錄下的appcompat.sh指令碼,發現也可以實現相同的檢測效果.所以有點懷疑,但是沒有Windows的裝置來測試,如果有試過的可以把結果告知一下.
結語
定位瞭解到專案中非SDK介面的使用情況後,就可以做出對應的調整,完成適配,避免crash.如果必須要用某種非SDK介面的話,可以向Google提出申請,請求地址如下:
https://issuetracker.google.com/issues/new?component=328403&template=1027267