Android資源管理器過程分析 & 插件化實現(xiàn)Hook 資源管理器的實現(xiàn)

簡 錄

概括[1]

資源分類
資源打包

自定義資源ID的取值范圍[2]

使用場景
自定義方式

Android資源管理器AssetManager的創(chuàng)建過程[3]

上下文環(huán)境解析
多個APK環(huán)境下資源的存儲方式
AssetsManger和Resources如何實現(xiàn)資源訪問的

Android-Framework-Plugin插件化資源創(chuàng)建[4]

概括

概括中主要講解資源的基礎(chǔ)認知及資源的打包過程和注意事項

資源分類

  • assets資源
  • res資源 > res目錄下的資源會被賦予ID.方便我們通過ID訪問資源
  • animator -> 屬性動畫
  • anim ->補間動畫
  • color ->顏色資源
  • drawable -> 圖片資源
  • layout -> 布局資源
  • menu ->菜單資源
  • raw ->任意格式資源,它同assets下資源一樣會原封不動的打入APK文件中,不過它仍會被賦予ID,我們也可以通過ID訪問它

Resources res = getResources();
InputStream is = res .openRawResource(R.raw.filename);

  • values ->描述一些簡單資源
  • xml ->描述應(yīng)用程序的配置信息資源
注意:
  • 上述9種類型資源,除了raw類型資源和Bitmap文件的drawable類型資源外,其余的資源都將在打包過程中編譯成二進制格式的xml文件,
    這些二進制文件分別有一個字符串資源池,用來保存文件中引用到的資源,
    這樣做的好處
  • 文件占用更小
  • 解析速度更快
  • Res資源在編譯完成后都會分配一個資源ID,會被保存到 R.java文件中與應(yīng)用程序的其他源文件一起編譯到程序中 ID唯一性,不唯一則出現(xiàn)資源沖突

資源打包過程

  • 除了assets和res/raw資源被原封不動打進APK之外,其他資源會被編譯成二進制文件打進APK
  • 除了assets資源之外,其他資源都會被賦予一個資源ID
  • 打包工具完成對資源的打包和編譯后會生成一個 resources.arsc 文件和 R.java 文件,前者是 資源索引表,后者是 資源ID表
  • AndroidManifest.xml同樣會被編譯成二進制的XML文件
  • 應(yīng)用程序通過AssetManager來訪問資源,或通過資源ID訪問,或通過文件名訪問

自定義資源ID的取值范圍

使用場景

當(dāng)我們在插件定義的資源打包是編譯到宿主資源鏈表時,為了避免這些資源與宿主的資源沖突,所以需要我們?yōu)樗拗鞯馁Y源定義一個ID范圍.

自定以資源方式

在Android資源中,有一種資源類型稱為Public,他們一般定義在res/values/public.xml文件中芝囤,形式如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--在宿主中指定這些id的范圍是為了使宿主各類資源的id和插件各類資源的id不重復(fù),否則會出錯(若沒出錯也僅是湊巧)-->
    <!-- 單獨指定屬性的資源范圍是為了支持主題屬性換膚  將end值設(shè)置為0100仆嗦,意思預(yù)留從0000到0100的id給插件屬性使用
        即插件的attr不可超過256個谆甜,這個值可以根據(jù)實際情況調(diào)整
     -->
    <public-padding type="attr" name="public_static_final_host_attr_"     start="0x7f010000" end="0x7f010100" />
    <!-- 除屬性外 其他類型的資源設(shè)置為  0x7f32開始 -->
    <public-padding type="drawable" name="public_static_final_host_drawable_" start="0x7f320000" end="0x7f320000" />
    <public-padding type="layout" name="public_static_final_host_layout_"   start="0x7f330000" end="0x7f330000" />
    <public-padding type="anim" name="public_static_final_host_anim_"     start="0x7f340000" end="0x7f340000" />
    <public-padding type="xml" name="public_static_final_host_xml_"      start="0x7f350000" end="0x7f350000" />
    <public-padding type="raw" name="public_static_final_host_raw_"      start="0x7f360000" end="0x7f360000" />
    <public-padding type="dimen" name="public_static_final_host_dimen_"    start="0x7f370000" end="0x7f370000" />
    <public-padding type="string" name="public_static_final_host_string_"   start="0x7f380000" end="0x7f380000" />
   <public-padding type="style" name="public_static_final_host_style_"    start="0x7f390000" end="0x7f390000" />
    <public-padding type="color" name="public_static_final_host_color_"    start="0x7f3a0000" end="0x7f3a0000" />
    <public-padding type="id" name="public_static_final_host_id_"       start="0x7f3b0000" end="0x7f3b0000" />
    <public-padding type="bool" name="public_static_final_host_bool_"     start="0x7f3c0000" end="0x7f3c0000" />
    <public-padding type="integer" name="public_static_final_host_int_"  start="0x7f3d0000" end="0x7f3d0000" />
    <public-padding type="array" name="public_static_final_host_array_"    start="0x7f3e0000" end="0x7f3e0000" />
    <public-padding type="menu" name="public_static_final_host_menu_"     start="0x7f3f0000" end="0x7f3f0000" />
    <public-padding type="mipmap" name="public_static_final_host_mipmap_"     start="0x7f400000" end="0x7f400000" />
    <public-padding type="animator" name="public_static_final_host_animator"     start="0x7f410000" end="0x7f410000" />
    <public-padding type="fraction" name="public_static_final_host_fraction"     start="0x7f420000" end="0x7f420000" />
    <public-padding type="font" name="public_static_final_host_font"     start="0x7f430000" end="0x7f430000" />
    <public-padding type="plurals" name="public_static_final_host_plurals"     start="0x7f440000" end="0x7f440000" />
    <public-padding type="interpolator" name="public_static_final_host_interpolator"     start="0x7f450000" end="0x7f450000" />
    <public-padding type="transition" name="public_static_final_host_transition"     start="0x7f460000" end="0x7f460000" />
    <public-padding type="_aapt" name="public_static_final_host__aapt"     start="0x7f470000" end="0x7f470000" />
</resources>
xml分析
  • type 用于指定資源類型
  • name 用于appt在編譯時重賦資源的name名稱,name_資源名
  • start 取值起始位置
  • end 取值結(jié)束位置

每當(dāng)aapt重新編譯被修改過的資源時,都會重新給這些資源賦予ID

Android資源管理器AssetManager的創(chuàng)建過程

上下文環(huán)境解析

  • 每個Activity都會關(guān)聯(lián)一個ContextImpl對象,Activity和ContextImpl都繼承于Context;
  • 所以Activity大部分成員函數(shù)通過都調(diào)用ContextImpl對象的對應(yīng)函數(shù)做處理的,其中訪問程序資源是通過調(diào)用ContextImpl對象的getResources()和getAssets() 函數(shù)來實現(xiàn)的
  • getResources()

返回一個Resources對象纫谅,通過Resources對象我們就可以通過資源ID訪問資源

  • getAssets()

返回一個AssetsManager對象,通過AssetsManager對象我們就可以通過文件名訪問被編譯過的資源文件

  • 事實上Resources也是通過AssetsManager來訪問資源文件的,只不過它會先通過資源ID查找到資源文件名

多個APK環(huán)境下資源的存儲方式

Android系統(tǒng)允許一個進程中存在多個apk文件,每個APK文件都會有一個全局的Resources對象和AssetsManager對象,

  • 全局的Resources對象存儲在對應(yīng)的ContextImpl對象的成員變量mResources中
  • 全局的AssetsManager對象存儲在對應(yīng)的Resources對象的成員變量mAssets中

AssetsManger和Resources如何實現(xiàn)資源訪問的

Resources訪問資源
  • Resources類中的成員函數(shù)getAssets(),通過getAssets()可以獲取Resources類中成員變量mAssets的AssetsManager對象,所以訪問資源最終實現(xiàn)仍在AssetsManager實現(xiàn)的
AssetsManager訪問資源
  • 1.AssetsManager類除了Java層的實現(xiàn)外,還有C++層對應(yīng)的實現(xiàn)。而Java層的AssetsManager類的功能就是通過C++層來實現(xiàn)的;
  • 2.Java層每個AssetsManager對象都有一個int類型的成員變量mObject,mObject保存的便是在C++層對應(yīng)的AssetsManager對象地址.
  • 3.通過mObject這個變量可以將Java層對象和C++層對象關(guān)聯(lián)起來
  • 4.C++層的AssetsManager類有三個重要的成員變量
  • mAssetPaths -> 資源存放目錄
  • mResources -> 指向一個資源索引表,以供Resources對象通過資源ID訪問資源
  • mConfig -> 設(shè)備的本地配置信息,包括屏幕的密度和大小、國家地區(qū)勾拉、語言等
    有了這三個變量后,C++層的AssetsManager類就可以訪問程序資源了
Android-Framework-Plugin插件化資源創(chuàng)建
  • 1.創(chuàng)建一個AssetManager的代理類的實例,因為是對AssetManager做代理,所以需要將AssetManasger的實例傳入到代理中
 HackAssetManager hackAssetManager = new HackAssetManager(assetMgr);
  • 2.在HackAssetManager中通過反射將assetPaths數(shù)組中的資源路徑添加進去
hackAssetManager.addAssetPaths(assetPaths);?
  • 3.完成以上步驟后我們需要創(chuàng)建字符串資源池來實現(xiàn)資源的添加
hackAssetManager.ensureStringBlocks();  //創(chuàng)建字符串資源池

4.現(xiàn)在我們可以獲取資源了

?Resources pluginRes = new PluginResourceWrapper(assetMgr, mainRes.getDisplayMetrics(),mainRes.getConfiguration(), pluginDescriptor);
// assetMgr 是我們?nèi)诤虾蟮腁sset資源
?//mainRes 是宿主的Resources實例,調(diào)用了其中的兩個屬性方法
//pluginDescriptor 是插件的??屬性數(shù)據(jù)序列化類實例?
//通過實例化此得到一個Resources資源實例,?

具體的實現(xiàn)代碼請移步Android-Fragmework-Plugin,GitHub地址

This ALL! Thanks EveryBody!


  1. 概括 ?

  2. 自定義資源ID的取值范圍 ?

  3. Android資源管理器AssetManager的創(chuàng)建過程 ?

  4. Android-Framework-Plugin插件化資源創(chuàng)建 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市批销,隨后出現(xiàn)的幾起案子顷蟀,更是在濱河造成了極大的恐慌鸣个,老刑警劉巖是趴,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唆途,死亡現(xiàn)場離奇詭異肛搬,居然都是意外死亡,警方通過查閱死者的電腦和手機鬼癣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腹纳,“玉大人,你說我怎么就攤上這事雄驹。” “怎么了蔬将?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長廉沮。 經(jīng)常有香客問我,道長坪稽,這世上最難降的妖魔是什么窒百? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上蔼水,老公的妹妹穿的比我還像新娘吊说。我一直安慰自己颁井,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蜀变,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贤惯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音雾袱,去河邊找鬼芹橡。 笑死煎殷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的珠移。 我是一名探鬼主播暇韧,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起巴席,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤堰塌,失蹤者是張志新(化名)和其女友劉穎场刑,沒想到半個月后牵现,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞎疼,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡捏萍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片片迅。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖耻台,靈堂內(nèi)的尸體忽然破棺而出扼菠,到底是詐尸還是另有隱情循榆,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布秧饮,位于F島的核電站浦楣,受9級特大地震影響咪辱,放射性物質(zhì)發(fā)生泄漏椎组。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一专筷、第九天 我趴在偏房一處隱蔽的房頂上張望磷蛹。 院中可真熱鬧溪烤,春花似錦、人聲如沸槽驶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烤镐。三九已至,卻和暖如春炮叶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镜悉。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工侣肄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吼具。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓矩距,卻偏偏與公主長得像,于是被迫代替她去往敵國和親陡蝇。 傳聞我的和親對象是個殘疾皇子哮肚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容