Android實現外掛程式化換膚 一

2021-10-23 16:13:57 字數 3817 閱讀 1919

何為外掛程式化換膚,顧名思義,就是通過外掛程式的形式向宿主apk新增資源(/顏色等資源)。宿主apk進行資源應用,最終將宿主apk上面的資源替換掉。在進行換膚之前,我們需要了解andorid布局檔案的解析流程,具體可以檢視

setcontentview原始碼解讀。3.1 控制項的生成 通過檢視

setcontentview原始碼解讀可以知道,我們進行換膚的核心操作就是替換layoutinflater類中的mfactory2變數。雖然mfactory2在activity啟動之前已經被賦值了,不過layoutinflater給我提供了修改mfactory2的入口(setfactory2方法)。setfactory2方法原始碼如下:

public

void

setfactory2

(factory2 factory)

if(factory == null)

//第一次呼叫之後mfactoryset將會被賦值為true,所以要想實現外掛程式化則必須在呼叫setfactory2中之前修改mfactoryset的值

mfactoryset =

true;if

(mfactory == null)

else

}

通過分析上述原始碼可以知道,要想二次給mfractory2賦值成功則必須要將mfractoryset的值修改為false。

3.2 apk中的資源的載入流程分析(android8.0 api26) 先來一張apk中的資源關係圖,如下所示:

此處用android8.0的原始碼來作分析,因為demo中使用的api介面是基於android8.0的。在android8.0之後demo中用到的api有些已經被谷歌標註為過時了,不過目前仍然可以用。資源載入的入口原始碼如下:

private

void

else

//...不相關**

}

(activitythread mainthread, loadedapk packageinfo)

上述packageinfo.getresources方法原始碼如下所示:

public resources getresources()

return mresources;

}

上述resourcesmanager.getinstance().getresources原始碼如下所示:

public

@nullable resources getresources

(@nullable ibinder activitytoken,

@nullable string resdir,

@nullable string[

] splitresdirs,

@nullable string[

] overlaydirs,

@nullable string[

] libdirs,

int displayid,

@nullable configuration overrideconfig,

@nonnull compatibilityinfo compatinfo,

@nullable classloader classloader)

finally

}

getorcreateresources方法原始碼如下所示:

private

@nullable resources getorcreateresources

(@nullable ibinder activitytoken,

@nonnull resourceskey key,

@nonnull classloader classloader)

return resources;

}}

上述createresourcesimpl方法原始碼如下:

private

@nullable resourcesimpl createresourcesimpl

(@nonnull resourceskey key)

final displaymetrics dm =

getdisplaymetrics

(key.mdisplayid, daj)

;final configuration config =

generateconfig

(key, dm)

;final resourcesimpl impl =

newresourcesimpl

(assets, dm, config, daj);if

(debug)

return impl;

}

上述createassetmanager方法原始碼如下所示:

protected

@nullable assetmanager createassetmanager

(@nonnull

final resourceskey key)}if

(key.msplitresdirs != null)}}

if(key.moverlaydirs != null)}if

(key.mlibdirs != null)}}

}return assets;

}

3.3 如何通過resources物件回去apk中的資源 宿主載入外掛程式的資源的簡易效果圖如下所示:

舉個例子通過resources物件回去apk中文字資源,**如下:

gettext

上述gettext的原始碼如下所示:

public charsequence gettext

(@stringres

int id)

throws notfoundexception

throw

newnotfoundexception

("string resource id #0x"

+ integer.

tohexstring

(id));

}

assertmanager中獲取資源id的四大核心方法如下所示:

//獲取資源id

/*package*/

native

final

intgetresourceidentifier

(string name,

string deftype,

string defpackage)

;//通過資源id獲取資源名稱

/*package*/

native

final string getresourcename

(int resid)

;//通過資源id獲取包名

/*package*/

native

final string getresourcepackagename

(int resid)

;//通過資源id獲取型別名

/*package*/

native

final string getresourcetypename

(int resid)

;

Android外掛程式換膚之入門實戰

學習自 首先是typedarray進行乙個定義,所以我們才能以src 的形式去宣告。所以我們需要關注typedarray.getdrawable方法。其實他的本質還是像我們平時一樣,通過resource去獲取drawable。通過resource去獲取drawable的流程大致如下 先去找resou...

Android應用的換膚實現(APK)

android應用換膚大概有如下幾種方式 skin apk是通過main apk skin apk的方式,需要在androidmanifest.xml檔案中配置的android shareduserid屬性值相同,從而實現主從apk能共享共享資源。實現如下 context context creat...

Android外掛程式化 動態載入jar 一

4.結束 dexclassloader 和 pathclassloader 的都是繼承與 basedexclassloader,是通過類載入 classloader 來載入查詢 class。pathclassloader只能載入已經安裝到android系統中的apk檔案,dexclassloader...