從 Android 9(API 級別 28)開始,此平臺對應用能使用的非 SDK 接口實施了限制。只要應用引用非 SDK 接口或嘗試使用反射或 JNI 來獲取其句柄,這些限制就適用。這些限制旨在幫助提高用戶體驗和開發者體驗,爲用戶下降應用發生崩潰的風險,同時爲開發者下降緊急發佈的風險java
一條消息瞬間席捲了整個開發圈子。會不會影響插件化?會不會影響熱修復?好在,對這些沒影響。然而,對一些很是hacker的手段,仍是有着不小的影響,好比上一篇的DNS hook libcore的方案。那麼,咱們如何解決呢?linux
若是你們不瞭解這個限制,能夠先去針對非 SDK 接口的限制這個文檔中瞭解一下,這裏簡單的說一下。當咱們訪問受限的接口時,會出現以下狀況。android
那麼,如何檢查你的應用中是否有使用受限的接口呢。咱們可使用veridex工具進行查看。用法以下git
### Linux x64
Download veridex-linux.zip, unzip the file and run with:
> ./appcompat.sh --dex-file=test.apk
### macOS
Download veridex-mac.zip, unzip the file and run with:
> ./appcompat.sh --dex-file=test.apk
複製代碼
通過檢查,若是發現沒有使用,那即是極好的,可是!!!若是使用了且無可替代怎麼辦?辦他!github
很早以前,360團隊就出了兩篇文章。 Android P 調用隱藏API限制原理 以及 突破Android P(Preview 1)對調用隱藏API限制的方法 。這兩篇文章也是咱們下面方案的原理來源。面試
這個方法一對應的是360文章中的方法三。主要代碼以下。bash
其中,fake_dlopen、fake_dlsym 使用的是Nougat_dlfunctions,主要是Android 7.0以上對dlopen、dlsym等函數作了限制。所以用這個庫。而MSHookFunction,則是大名鼎鼎的cydiasubstrate。微信
上面的代碼只解決了反射方法的問題。我按照這種思路去解決字段問題的時候發現。架構
GetDeclaredField是inline的,沒法切入。而CreateFromArtField又是hidden的,也很差切入。app
所以,放棄了這種方法。
這裏對應的方法二,對應的是360文章中的方法二,也就是修改classloader的方式。代碼以下。
沒錯,代碼就是這麼點。這樣,咱們就能夠在ReflectionHelper中調用非公開API了。可是這裏會依賴Nougat_dlfunctions這個庫。
既然是修改classloader,那麼咱們爲何不在java層修改呢。代碼以下。
而這裏用的相關反射只是light級別的,沒有什麼影響。反而代碼量超小,也不依賴其餘。
這個方案來自 @區長 大神
方法四仍是存在一點問題。若是之後把classloader加入到深灰或者黑名單,那就僵硬了。因此,咱們不用反射,直接用unsafe去修改。代碼這就不貼了。爲了獲得classloader的偏移量,咱們寫一個和Class結構同樣的類,用這個類獲得的classLoader的偏移量和Class是同樣的。
田維術 VMRuntime.setHiddenApiExemptions 方法,連接在這裏點我查看
以爲寫的還行的朋友能夠關注如下個人微信公衆號,這裏用於交流一些Android基礎架構、疑難雜症、面試等等問題。