手把手教你解析Resources.arsc

一、前言

对于APK里面的Resources.arsc文件大家应该都知道是干什么的(不知道的请看我的另一篇文章Android应用程序资源文件的编译和打包原理),它实际上就是App的资源索引表。下面我会结合实例对它的格式做一下剖析,读完这篇文章应该能够知道Resources.arsc的格式,并可以从二进制的文件中查找到资源的相关信息,或者根据资源的id可以定位到二进制文件中的位置。不过本人对Android资源文件的有一些相关概念并不是特别熟悉,所以文章中有很多地方也并不明白,如有错误欢迎指正!


二、R.java文件及资源ID

首先先介绍一下我们在Android应用开发过程中程序中用的资源的id,相信大家都知道R.java文件,这个是通过aapt对资源文件进行编译生成的资源id文件,这样我们程序中使用资源文件更加方便。举例我们先看一下原始的资源文件res/values/strings.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Cert</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

</resources>

代码段1

这里先介绍几个概念,上面的app_name和hello_world这些叫做资源项名称(其它的还有windowActionBar、ActionBarTabStyle类似这种),而它们对应的资源项类型就是string(其它的还有attr、drawable类似这些),资源项的值就是Cert和Hello world!这些。


下面是对应R.java文件的内容:

public final class R {
              ...
    public static final class string {
                     ...
        /**  Description of the choose target button in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] 
         */
        public static final int abc_shareactionprovider_share_with=0x7f0a000c;
        /**  Description of a share target (both in the list of such or the default share button) in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] 
         */
        public static final int abc_shareactionprovider_share_with_application=0x7f0a000b;
        public static final int action_settings=0x7f0a000f;
        public static final int app_name=0x7f0a000d;
        public static final int hello_world=0x7f0a000e;
    }
                     ...
}

代码段2

可以看到每个资源文件在R中都是一个class,每个资源项名称都分配了一个id,id值是一个四字节无符号整数,格式是这样的:0xpptteeee,(p代表的是package,t代表的是type,e代表的是entry),最高字节代表Package ID,次高字节代表Type ID,后面两个字节代表Entry ID。

Package ID相当于是一个命名空间,限定资源的来源。Android系统当前定义了两个资源命令空间,其中一个系统资源命令空间,它的Package ID等于0x01,另外一个是应用程序资源命令空间,它的Package ID等于0x7f。所有位于[0x01, 0x7f]之间的Package ID都是合法的,而在这个范围之外的都是非法的Package ID。前面提到的系统资源包package-export.apk的Package ID就等于0x01,而我们在应用程序中定义的资源的Package ID的值都等于0x7f,这一点可以通过生成的R.java文件来验证。

Type ID是指资源的类型ID。资源的类型有animator、anim、color、drawable、layout、menu、raw、string和xml等等若干种,每一种都会被赋予一个ID。

Entry ID是指每一个资源在其所属的资源类型中所出现的次序。注意,不同类型的资源的Entry ID有可能是相同的,但是由于它们的类型不同,我们仍然可以通过其资源ID来区别开来。


三、解析Resources.arsc


1. Resources.arsc文件格式

下面我们开始看Resources.arsc(后面截图给出的resources.arsc文件的二进制内容都是与上面代码段1和代码段2相对应的),首先看一下文件的格式,如下面两个图:


图1


图2

以上两个图都是Resources.arsc文件的格式,图1是从网上找的,其中很多项都展开了,不了解对应的数据结构肯定看不懂,所以我自己画了图2(画图好蛋疼的说~抓狂),相对来说更容易接受一点,这里都放出来做个对照吧。Resources.arsc对应的数据结构的定义在Android源码/frameworks/base/include/androidfw/ResourceType.h中,大家可以自己去看一下。


2. chunk

下面我来从上到下介绍一下文件的格式,首先是chunk概念,整个文件是由一系列的chunk构成的,算是整个文件划分的基本单位吧,实际上就是把整个文件无差别的划分成多个模块,每个模块就是一个chunk,结构更加清晰。每个chunk是最前面是一个ResChunk_header的结构体,描述这个chunk的信息,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
  • 13
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值