外掛化技術:宿主訪問外掛資源

androidwing發表於2017-02-07

本文同步自wing的地方酒館

最近在搞外掛化,16年很火的東西,我又拖了1年才來研究,哈哈哈,正確下一個熱門技術能提前一些吧。

今天想跟大家討論一下我在研究外掛化過程中,遇到的一個容易混淆的點,那就是資源訪問。

首先感謝下在外掛化道路上的老司機,無私的奉獻資料。

看過很多外掛化的文章,都提到了一大痛點是資源訪問的問題。解決方法很通用,都是通過反射使用 AssetManager 的 addAssetPath 方法,把外掛apk路徑新增進去。再把系統的resource替換掉,就可以訪問到資源了。

這時候,大部分部落格會新增一句:

資源訪問是一個痛點,所以用以上方式解決R引用

但是這裡有一個及其容易混淆的地方,就是 “解決了R引用”,那麼到底實際上是解決了誰的R引用問題呢? 是宿主訪問外掛的資源呢,還是外掛訪問外掛的資源呢?

為了講解清楚我來畫一張圖:

外掛化技術:宿主訪問外掛資源

如上圖在沒有替換掉Resources的時候。

由於每個apk只能訪問自己的res,所以這時候使用hook newActivity建立的Activity物件,是無法訪問到外掛res的,雖然這個Activity確實是外掛中的Activity,但是實際上是載入在宿主裡的resource,所以也就是有個隔離,因此必須替換resource

外掛化技術:宿主訪問外掛資源

當AddPath以後,關係就變成了如上圖的關係,此時建立的Activity的例項,也就是宿主的順理成章能拿到外掛的資源。

混淆點就是在這裡,在之前網上部落格文章中說的解決了資源訪問問題,實際上是指外掛Activity不能訪問外掛本身的資源,而不是說宿主Activity訪問外掛的資源

宿主Activity如何訪問外掛資源?

經過大量搜尋,跟小夥伴討論得知可以通過如下方式獲得外掛資源:

getResources().getString(getResources()
.getIdentifier("plugin", "string","com.your.name")),
 Toast.LENGTH_SHORT).show();複製程式碼

這個方法是根據資源名稱,來獲取資源id,所以就可以根據id拿到資源了。

比如上面的例子就是通過getIdentifier()方法尋找名稱為plugin的string資源。當然你要提供外掛的包名。

相關文章