android apk resources.arsc,可能是全网讲最细的安卓resources.arsc解析教程(一)

aapt工具在编译资源会将一些资源或者资源索引打包成resources.arsc。这个文件以二进制数据的形式记录数据,c/c++加载起来特别方便。

了解resources.arsc的结构对理解安卓的资源加载原理有很重要的帮助。

这几天写resources.arsc解析工具时候在网上搜到了不少的资料、博客,但是它们写的都不是特别的详细,都会漏掉一些东西没有提。导致在实现的时候遇到了很多的坑。这里我希望尽量把自己总结出来的东西一步步都列出来,尽量做到只需要看这篇博客就能自己实现一个resources.arsc的解析器。

这个工具已经在github上开源(使用C++11,已经在mac和ubuntu上报make编译通过正常运行,Windows的同学就只好说声抱歉了),感兴趣的同学也可以直接下载下来玩玩。

总体结构

resources.arsc是以一个个Chunk块的形式组织的,Chunk的头部信息记录了这个Chunk的类型、长度等数据。

从整体上来看,其结构为:资源索引表头部+字符串资源池+N个Package数据块:

1.png

头部数据解析

整个resources.arsc就是一个Chunk块,所以文件的开头就是这个Chunk的头部信息.不过需要注意的是resources.arsc文件采用小端编码方式.所以数据应该按字节从后往前读。

头部的结构如下:

头部类型(两个字节),头部大小(两个字节),Chunk块大小(四个字节)

我们找一个apk文件,将它后缀改成.zip直接解压,就可以得到resources.arsc,这里实际举个例子,用编辑工具查看到resources.arsc的前8个字节的数据,这里以16进制显示:

0200 0c00 acb6 0300

首先头部类型的两个字节是0200(每两个16进制数字代表了一个字节),但是这里是小端序,所以要从后往前读,得到实际的值0x0002。

02 00 -> 00 02

resources.arsc内部记录的数据类型在ResourceTypes.h里面定义,我们找到头部类型的枚举,可以查到0x0002对应的类型是RES_TABLE_TYPE。返回去看上面的图,可以看到类型的确是RES_TABLE_TYPE。

enum {

RES_NULL_TYPE = 0x0000,

RES_STRING_POOL_TYPE = 0x0001,

RES_TABLE_TYPE = 0x0002,

RES_XML_TYPE = 0x0003,

// Chunk types in RES_XML_TYPE

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,

// This contains a uint32_t array mapping strings in the string

// pool back to resource identifiers. It is optional.

RES_XML_RESOURCE_MAP_TYPE = 0x0180,

// Chunk types in RES_TABLE_TYPE

RES_TABLE_PACKAGE_TYPE = 0x0200,

RES_TABLE_TYPE_TYPE = 0x0201,

RES_TABLE_TYPE_SPEC_TYPE = 0x0202,

RES_TABLE_LIBRARY_TYPE = 0x0203

};

接着是头部大小的两个字节0c00(每两个16进制数字代表了一个字节),从后往前读得到实际值0x000c,也就是说这个头部大小有12个字节

0c 00 -> 00 0c

再接着的是Chunk块大小的四个字节acb6 0300(每两个16进制数字代表了一个字节),从后往前读得到实际值0x0003b6ac,转换回十进制是243372,也就是说resources.arsc文件的大小是243372字节。

ac b6 03 00 -> 00 03 b6 ac

我们可以用wc命令查看这个文件的大小:

wc resources.arsc

277 2932 243372 resources.arsc

resources.arsc文件这样组织的原因是可以很方便的使用c/c++去加载。

我们在源码里面找到Chunk头部信息的ResChunk_header结构体:

/**

* Header that appears at the front of every data chunk in a resource.

*/

struct ResChunk_header

{

// Type identifier for this chunk. The meaning of this value depends

// on the containing chunk.

<

你可能感兴趣的:(android,apk,resources.arsc)