rsources.arsc格式详解(2020年)
2020-01-10 本文已影响0人
河里的枇杷树
首先我们说一下 为什么 要写这篇文章
- 网上关于 rsources.arsc 文件解析的文章 内容较老
- 很少对每个chunk的含义做解释,或者 解释比较含糊
rsources.arsc 文件解析文章里基本上都有一张‘神图’但是里面缺少了一些内容。所以我就在 这张图的基础上,重新画了一张,增加了一些内容,最后对 各个 chunk 中包含的内容进行讲解。
arsc.png每一块的含义(顺序从左至右,从上到下)
ResTableHeader
- RES_TABLE_TYPE:占用2 字节 ,表示 rsources.arsc 文件整块的类型
- 头大小:占 两个字节,表示 RES_TABLE_TYPE + 头大小+ 块大小 + package数 一共占用的字节数 也就是 12个字节
- 块大小:占 4字节 ,表示整个arsc内容块占用的字节数
- package数:占 4字节,表示被编译的资源包个数,一般就一个 。不知道怎么样会有多个
下面为了方便我就不写 占用空间了。看图就可以一目了然
ResStringPool
- RES_STRING_POOL_TYPE: StringPool的类型
- 头大小:和ResTableHeader的头大小一样 所以占用 也就是 28个字节
- 块大小:StringPool整块大小
- 字符串数:可解析出字符串的个数
- style数:可解析出style的个数 不知道是什么style,待研究
- 标记:字符串的属性,可取值包括0x000(UTF-16),0x001(字符串经过排序)、0X100(UTF-8)和他们的组合值
- 字符串起始位置 : 字符串 相对于 ResStringPool的偏移量
- style起始位置:style 相对于 ResStringPool的偏移量
- 字符串偏移数组:保存的是每个字符串的索引。可已通过 字符串个数 解析出来,也可以配合 字符串 解析出不同的字符串。
- style偏移数组:保存的是每个style的索引。可已通过 style个数 解析出来,也可以配合 字符串 解析出不同的style。
- 字符串:保存具体字符串的地方,有自己的格式,前两个字节记录了字符串长度,字符串以0或者00结尾(和编码方式(utf-8或者utf-16有关)) 存储的是layout,drawable 文件夹下文件的全路径 和 Strings.xml中的 值(key的话是存在 资源项名称字符串池中的)
例如:
res/anim/abc_slide_in_bottom.xml
如果是 utf-8,则字符串以 0x00 结尾,开头前两个字节分别表示 u8len 和 u16len。如果是 utf-16,则字符串以 0x0000 结尾,开头前两个字节表示 u16len,没有 u8len 字段。(u16len 和 u8len,分别代表 UTF-8 和 UTF-16 下的字符串长度)
- style:目前不太清楚保存的什么
ResTablePackage
- RES_TABLE_PACKAGE_TYPE: ResTablePackage的类型
- 头大小:ResTablePackage头部大小
- 块大小:ResTablePackage整块大小
- package id: 一般用户包的值为0X7F,系统资源包为0X01
- package name:就是 APP中配置的包名
- typeStrings: 资源类型字符串池 的偏移量(用于定位 资源类型字符串池)
- lastPublicType:最后一个导出的Public类型字符串在类型字符串资源池中的索引,目前这个值设置为类型字符串资源池的元素的个数
- keyStrings:资源项目名称字符串池 的偏移量(用于定位 资源项目名称字符串池)
- lastPublicKey:最后一个导出的Public资源项名称字符串在资源项名称字符串资源池中的索引,目前这个值设置为资源项名称字符串资源池的元素的个数,目前没发现用途
- typeIdOffset : 表示类型id的偏移 有可能存在也有可能不存在,我们需要判断头大小和 1-8所占空间是否相当,如果相等就说明不包含,如果不相等就说明包含。 如果包含的话 我们在解析 RES_TABLE_LIBRARY_TYPE 的typeId时要得到真正的 typeId 就要减去 typeIdOffset
- 资源类型字符串池:用于存储资源类型,如 string,layout,drawable等 。他的结构和 ResStringPool 是一样的。
- 资源项名称字符串池:用于存储 资源名称,比如layout的名字,string的名字,color的名字。也是一个 ResStringPool
ResTypeLibrary
是5.0之后才加入的,所以网上那么比较陈旧的文章中没有提及。它的作用就是正确的查找 ResTable_map_entry 类型Entry数据的parent。一般用不到,aapt在构建arsc文件时 会在 packageId 不是 0X7F(用户包) 才会加入。不一定存在
- type= RES_TABLE_LIBRARY_TYPE
- 头大小
- 块大小
- count:library的个数
- packageid:library 的 id
- package name:library的包名
ResTypeSpecChunk
用来描述资源项的配置差异性。系统根据不同设备的配置差异就可以加载不同的资源项(会有多个)
- type=RES_TABLE_TYPE_SPEC_TYPE
- 头大小
- 块大小
- type id : 资源类型id ,从1开始(对应于资源标识符中类型位的值)。 0无效。
- 保留字段:一共两个占3个字节。 一个占一个字节一个占两个字节。默认都是0
- entryCount:本类型的资源项个数(指名称相同的资源项的个数)
- 资源 spce 数组:包含 资源项组spec数 个 uint_32 数组,数组每个元素都是用来描述资源项的配置差异性的。
ResTypeInfocChunk
资源项的具体信息,包括资源项的名称,类型,值和配置等等
- type=RES_TABLE_TYPE_TYPE
- 头大小
- 块大小
- type id : 资源类型id ,从1开始(对应于资源标识符中类型位的值)。 0无效。
- flags :占用一个字节
- 保留字段:一共占2个字节。
- entryCount:一共有多少组
- entriesStart:ResTable_entry偏移数组 的起始位置
- config大小: ResTable_config所占大小
- 运营商
.... - 屏幕尺寸
- entry偏移数组:记录偏移量 ,有可能是 -1,也就是不存在
- entry大小:entry块的大小
- flags: 如果为1的话,那就ResTable_map_entry 如果不是 那就是 不同的 entry(
至于什么是 mapEntry 什么是 entry 后面会讲到
) - entry index:资源项目名称 在 资源项目名 字符串池中的索引。可以获取到 资源名称。比如 layout的名字
ResTable_entry
- entry size:
- 保留字段:
- dataType:entry所包含的数据类型 ,String ,Float 等
- data:(完整资源项目名称index (下标)) 通过这个再加上 全局资源项目池 就可以拿到对应 文件的全路径 如res/anim/abc_slide_in_bottom.xml 可能为无效值
用于表示这种 key/value形式的
1.png
ResTable_map_entry
- parent :比如 style中 依赖的 的parent
- count:包含 ResTable_entry 的数量
- name: 比如 style中 依赖的 的name
- Res_value大小:
- 保留字段
- 数据类型:在 ResourcesType.h文件的 Res_value 结构体中有定义 可以为 String Float等
- data:(完整资源项目名称index (下标)) 通过这个再加上 全局资源项目池 就可以拿到对应 文件的全路径 如res/anim/abc_slide_in_bottom.xml 可能为无效值
用于表示这种形式的
2.png
注
- 本篇文章并没有对 rsources.arsc 文件的解析过程如果 想了解建议参考 https://github.com/NiLuogege/AndResGuardDebug.这个是我阅读 AndResGuard 源码时的项目,里面有详细的 注释
参考
1. https://www.jianshu.com/p/d62efb89b319
2. https://blog.csdn.net/chzphoenix/article/details/80567037
3. https://www.jianshu.com/p/93a38bebeaff
4. https://www.jianshu.com/p/3cc131db2002
5. 微信官方公众号出品