何為外掛程式化換膚,顧名思義,就是通過外掛程式的形式向宿主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...