目录
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。
2、RES_TABLE_TYPE_TYPE
Config List包含若干段数据结构
每段结构都是一个ResTable_type之后紧跟着ResTable_entry偏移数组和若干ResTable_entry。
示例如下:
3、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;
};
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偏移数组
5、ResTable_entry(非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;
};
- 0800 是ResTable_entry大小,即8byte
- 0000 是flag,0x01(字序)表示是bag,0x00则是非bag
- 87020000 是该资源项对应的字符串资源的索引
6、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;
};
- 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
- 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
struct ResTable_map_entry : public ResTable_entry
{
//指向父ResTable_map_entry的资源ID,如果没有父ResTable_map_entry,则等于0。
ResTable_ref parent;
//等于后面ResTable_map的数量
uint32_t count;
};
- 1000 是ResTable_entry大小,即0x10(16)byte
- 0100 是flag,0x01(字序)表示是bag,0x00则是非bag
- EA020000 是该资源项对应的字符串资源的索引
- C700097F 就是parent,因为例子是style,所以是这style的parent的resId,即0x7F0900C7
- 03000000 是ResTable_map的数量,即0x03(字序)
struct ResTable_map
{
//bag资源项ID
ResTable_ref name;
//bag资源项值
Res_value value;
};
例子中有三个,我们拿第一个举例:

8、总结
