resource.arsc二进制内容解析 之 RES_TABLE_TYPE_TYPE (Config List)
目錄
1、resource.arsc結構
2、RES_TABLE_TYPE_TYPE
3、ResTable_type
4、ResTable_entry偏移數組
5、ResTable_entry(非bag)
6、Res_value
7、bag類型的RES_TABLE_TYPE_TYPE
8、總結
1、resource.arsc結構
我們先來看resource.arsc的結構如圖:
(本來網上有一張神圖,但是結構表現的不夠清晰,而且比較舊了,缺少了一些新的東西,所以我根據神圖自己又重新整理了一張架構圖,其中新的東西是指Dynamic package reference,具體可以閱讀《resource.arsc二進制內容解析 之 Dynamic package reference》)
在package結構下可以看到有Type Spec(類型規范數據塊)和Config List,這塊內容是資源索引表中最重要的部分。這一部分也是同一個資源ID在不同配置下,找到不同資源文件的關鍵。
該部分的整體結構以資源類型Type分段,每段的數據結構相似,都是以ResTable_typeSpec開頭,后面緊跟著一個spec數組,和Config List。
Config List就是我們今天研究的關鍵,這里面包含一些列的RES_TABLE_TYPE_TYPE結構的數據。?
2、RES_TABLE_TYPE_TYPE
Config List包含若干段數據結構
每段結構都是一個ResTable_type之后緊跟著ResTable_entry偏移數組和若干ResTable_entry。
示例如下:
00000000 00000000?01024C00 500B0000 08000000 8D000000 80020000 38000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000?00000000?10000000 20000000 30000000 40000000 50000000 60000000 70000000 80000000 90000000 A0000000 B0000000 C0000000 D0000000 E0000000 F0000000 00010000 10010000 20010000 ... 50080000 60080000 70080000 80080000 90080000 A0080000 B0080000 C0080000 08000000 5F020000 08000005 01300000 08000000 60020000 08000005 01380000 08000000 61020000 08000005 01280000 08000000 62020000 08000005 01100000 ... 08000000 86020000 08000005 01240000 08000000 87020000 08000001 2E00087F 注意ResTable_entry有兩種類型:bag和非bag。示例中僅僅是非bag類型,bag類型后面會細說。 下面我們根據示例來一點點講解ResTable_type的結構。3、ResTable_type
首先是ResTable_type,結構如下: struct ResTable_type { struct ResChunk_header header; enum { NO_ENTRY = 0xFFFFFFFF }; //標識資源的Type ID uint8_t id; //保留,始終為0 uint8_t res0; //保留,始終為0 uint16_t res1; //等于本類型的資源項個數,指名稱相同的資源項的個數。 uint32_t entryCount; //等于資源項數據塊相對頭部的偏移值。 uint32_t entriesStart; //指向一個ResTable_config,用來描述配置信息,地區,語言,分辨率等 ResTable_config config; }; 其中ResChunk_header的結構如下: struct ResChunk_header { enum { RES_NULL_TYPE = 0x0000, RES_STRING_POOL_TYPE = 0x0001, RES_TABLE_TYPE = 0x0002, RES_XML_TYPE = 0x0003, RES_XML_FIRST_CHUNK_TYPE = 0x0100, RES_XML_START_NAMESPACE_TYPE= 0x0100, RES_XML_END_NAMESPACE_TYPE = 0x0101, RES_XML_START_ELEMENT_TYPE = 0x0102, RES_XML_END_ELEMENT_TYPE = 0x0103, RES_XML_CDATA_TYPE = 0x0104, RES_XML_LAST_CHUNK_TYPE = 0x017f, RES_XML_RESOURCE_MAP_TYPE = 0x0180, RES_TABLE_PACKAGE_TYPE = 0x0200, RES_TABLE_TYPE_TYPE = 0x0201, RES_TABLE_TYPE_SPEC_TYPE = 0x0202 }; //當前這個chunk的類型 uint16_t type; //當前這個chunk的頭部大小 uint16_t headerSize; //當前這個chunk的大小 uint32_t size; };ResTable_type就是上面橙色的部分,如下:
01024C00 500B0000 08000000 8D000000 80020000 38000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
- 01024C00 500B0000 是header,其中type是0x201(字序),即RES_TABLE_TYPE_TYPE;頭部大小是0x4c,也就是76個;整個chunk大小是0xb50
- 08000000 是id+res0+res1,所以資源的TypeId是0x08(在示例中是dimen類型的資源,所以是非bag,后面會講)
- 8D000000 是entryCount,即資源個數為141(注意字序)
- 80020000 是entriesStart,即資源數據塊相對于頭部的偏移量,即偏移0x280(字序)。例子中ResTable_type的大小為76byte;資源個數為141個,所以后面偏移數組有141個,每個偏移量占4byte,則是564byte。這樣到資源數據部分正好有640byte,即0x280。偏移數組后面會講
- 剩下的就是config了,其中38000000是config的數量,即56個,加上38000000也正好有56byte
4、ResTable_entry偏移數組
在ResTable_type緊跟著是ResTable_entry偏移數組,即綠色部分,每4byte為一個偏移量(相對于資源數據塊起始位置的偏移,本例子即頭部偏移0x280后的位置),一共有entryCount個即141個偏移量。 這塊沒必要要詳細解釋。但是我們注意到例子中這部分偏移量是16byte遞增的,說明后面的資源數據塊每塊是16byte,這個后面我們可以驗證。5、ResTable_entry(非bag)
“ResTable_entry偏移數組”后面就是一系列資源數據塊(ResTable_entry),即藍色部分 數據塊分兩種,bag和非bag。bag就是有一系列屬性的,比如attr、style等。非bag就是單個的,比如color、dimen等 數據塊是由ResTable_entry和一個或多個Res_value組成。 非bag的數據塊是由ResTable_entry和一個Res_value組成;bag數據塊則由ResTable_map_entry(繼承自ResTable_entry)和一個或多個Res_value組成。 這里先看非bag數據塊,示例中就是非bag數據塊。數據結構如下: struct ResTable_entry { //表示資源項頭部大小。 uint16_t size; enum { //如果flags此位為1,則ResTable_entry后跟隨ResTable_map數組,為0則跟隨一個Res_value。 FLAG_COMPLEX = 0x0001, //如果此位為1,這個一個被引用的資源項 FLAG_PUBLIC = 0x0002 }; //資源項標志位 uint16_t flags; //資源項名稱在資源項名稱字符串資源池的索引 struct ResStringPool_ref key; }; 通過上面我們知道示例中每個數據塊都是16byte,我們拿其中一個來舉例: 08000000 87020000 08000001 2E00087F 前8byte就是ResTable_entry,后8byte是Res_value(后面再講),一點點細說- 0800 是ResTable_entry大小,即8byte
- 0000 是flag,0x01(字序)表示是bag,0x00則是非bag
- 87020000 是該資源項對應的字符串資源的索引
6、Res_value
ResTable_entry后面跟著就是Res_value,它的結構如下: struct Res_value { //Res_value頭部大小 uint16_t size; //保留,始終為0 uint8_t res0; enum { TYPE_NULL = 0x00, TYPE_REFERENCE = 0x01, TYPE_ATTRIBUTE = 0x02, TYPE_STRING = 0x03, TYPE_FLOAT = 0x04, TYPE_DIMENSION = 0x05, TYPE_FRACTION = 0x06, TYPE_FIRST_INT = 0x10, TYPE_INT_DEC = 0x10, TYPE_INT_HEX = 0x11, TYPE_INT_BOOLEAN = 0x12, TYPE_FIRST_COLOR_INT = 0x1c, TYPE_INT_COLOR_ARGB8 = 0x1c, TYPE_INT_COLOR_ARGB8 = 0x1c, TYPE_INT_COLOR_RGB8 = 0x1d, TYPE_INT_COLOR_ARGB4 = 0x1e, TYPE_INT_COLOR_RGB4 = 0x1f, TYPE_LAST_COLOR_INT = 0x1f, TYPE_LAST_INT = 0x1f }; //數據的類型,可以從上面的枚舉類型中獲取 uint8_t dataType; //數據對應的索引 uint32_t data; }; 還用上面的例子來說,如下: 08000000 87020000 08000001 2E00087F 前8byte就是ResTable_entry(前面說過來),后8byte就是Res_value,一點點細說- 0800 是Res_value頭部大小,非bag就是Res_value的大小,即8byte
- 00 是res0,固定值
- 01? 是dataType,01表示是引用,即后面的data是一個resId
- 2E00087F 是數據索引,例子中是一個resId,即0x7F08002E,上面知道type08是dimen,所以這是一個dimen資源
7、bag類型的RES_TABLE_TYPE_TYPE
上面的例子是非bag,下面我們說說bag的例子,示例如下: 00000000 00000000?01024C00 90420000 09000000 7B010000 38060000 38000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000?00000000 34000000 5C000000 6C000000 7C000000 98000000 A8000000 B8000000 C8000000 D8000000 E8000000 ... 4C3A0000 8C3A0000 B43A0000 D03A0000 343B0000 743B0000 903B0000 F43B0000? 10000100 EA020000 C700097F 03000000 F300017F 08000005 01180000 F400017F 08000005 01030000 F700017F 08000005 01120000 10000100 EB020000 D200097D 02000000 3601017F 08000010 ... 與非bag相同的部分我們就簡單說一下,重點講不同的部分。 首先、ResTable_type即橙色部分:- 01024C00 90420000 是header,type同樣是0x201
- 0900000?是id+res0+res1,所以資源的TypeId是0x09(在示例中是style類型的資源,所以是bag)
- 7B010000 有0x17b個ResTable_entry
- 38060000 資源數據塊相對與頭部偏移0x638。頭部大小為76;偏移數組0x17b個,每個4byte。加起來正好0x638
- 后面是config,其中38000000是config的數量,即56個,加上38000000也正好有56byte
- 1000 是ResTable_entry大小,即0x10(16)byte
- 0100 是flag,0x01(字序)表示是bag,0x00則是非bag
- EA020000?是該資源項對應的字符串資源的索引
- C700097F 就是parent,因為例子是style,所以是這style的parent的resId,即0x7F0900C7
- 03000000? 是ResTable_map的數量,即0x03(字序)
?
8、總結
?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的resource.arsc二进制内容解析 之 RES_TABLE_TYPE_TYPE (Config List)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ListView和GridView的缓存
- 下一篇: gradle编译打包过程 之 Proce