Androi P之後Google可能會禁止使用反射來獲取隱藏方法的呼叫,雖然在preview版本中只會以log的形式提示,但後續的版本可能會在使用反射時直接丟擲錯誤。
這裡提供其中一種破解反射禁止的方法,不過這種方法也有侷限,就是隻能用於本來已經是public或者static的隱藏方法。
對於這種型別的隱藏方法,我們之前的解決途徑是通過反射來獲取,因為雖然是public,但是方法被@hidden註解過,所以沒法直接呼叫。
但雖然不能用反射,直接呼叫卻是可以的。這就是具體的思路。
一、關於隱藏方法
我們知道在Android原始碼中有部分程式碼是不允許開發者使用的,這裡要分兩種情況。
· 沒有打包進android.jar的類和方法,這部分不是隱藏的
· 打包進android.jar裡的隱藏類和方法
如果檢視原始碼,會發現有很多程式碼其實沒有打進android.jar,比如internal包下的類,其中就有WindowManagerService。
這部分類之所以不打進android.jar,目的是這些類是隻給android內部使用的,不希望開發者使用。
今天只說明對於沒有打包進 android.jar的類,在不用反射的情況下的使用方法。
二、用provided的方式提供丟失的類
在gradle專案裡,可以用provided的方式引入 java library,這樣引入的library不會被打包進最終的apk裡。
在gradle中這麼寫,
dependencies {
provided project(':libhookandroid')
}
複製程式碼
舉個例子,比方這時候要用 ActivityThread,這裡面有個 public方法 currentActivityThread(),我們要呼叫它,那麼可以在lib專案下按報名建一個類
public class ActivityThread{
public static ActivityThread currentActivityThread(){
return null;
}
}
複製程式碼
為何可以return null呢?
因為它不會最終編譯進apk,執行時呼叫的仍然是Android裡的ActivityThread,那裡有真正的實現邏輯,我們這裡只是做了個殼用來保證編譯時不會有問題。
寫完lib後在主工程裡就可以直接呼叫了,
ActivityThread thread = ActivityThread.currentActivityThread();
複製程式碼
因為是public方法,所以也不需要反射。
三、總結
對於Android裡沒有被打進 android.jar包中的類,可以通過 provided library的方式提供呼叫,
雖然P禁用了反射,但是直接呼叫是可以的。
然而缺點也是很明顯,它不能用到 protected或者 private的方法。
對於其他的情況,我們可以通過修改apk的class loader改成 BootStrapClassLoader來實現繞過這個限制。
看過之前文章的朋友應該知道 BootStrapClassLoader是終極 ClassLoader,以後我們會介紹通過它來繞過限制的方法。