android 资源那些事(一)编译 与 打包

最近在整理自己项目中关于插件框架的技术文档。写着写着发现自己有很多知识了解的不是很全,为此花了大把时间学习。今天先聊聊关于Android Resource 知识。这个系列会写三篇。

概述

一个APK文件,本质就是一个压缩包,通常来说解压后,我们能看到如下东西:

  1. 二进制的AndroidManifest.xml
  2. assets资源
  3. classes.dex
  4. kotlin代码(如果项目中使用了Kotlin编程,就有,否则没有)
  5. lib包
  6. res文件夹
  7. resources.arsc
  8. 签名信息META-INFO文件;

在上面的介绍中,和资源相关的就是assets资源、 resources.arsc、res文件夹以及AndroidManifest.xml。我们发现,在没有编译打包前,这些资源在我们项目中基本上都是以xml文件形式存在的(assets 里的资源除外,它们不参与编译),编译打包后几乎都变成了二进制的东西,有点神奇,Android 为啥要这样设计。

一、资源打包

Android是通过aapt(Android Asset Package Tool)把资源文件打包到apk里的。看下apk 经典的打包流程图。
android 资源那些事(一)编译 与 打包_第1张图片
aapt 全名Android Asset Package Tool, 是官方SDK自带的资源打包工具,是一个可执行文件,具体在 sdk/build-tools/&sdkversion/。我们也可以通过将其加到环境变量中,然后直接在命令行中通过调用aapt命令来执行一些操作,具体命令参数可参考aapt。因为开发过程中执行一个 assembleDebug task就能生成一个debug apk,由此我们也可以推测最终是在执行gradle task中完成aapt的调用,即gradle task最终生成一个AndroidBuilder,在其中构造出最终的aapt编译命令:

aapt --package -v xxxx -fxxx

二、资源编译流程

  • 1、解析AndroidManifest.xml :解析AndroidManifest.xml是为了获得要编译资源的应用程序的包名称,进而构造ResourceTable对象,利用ResourceTable对象来完成R.java和resources.arsc的生成,相当于创建一个资源表。
  • 2、添加被引用的资源包:我们工程中会引入一些系统资源,比如R.color.white,他们都不在本工程中,而是在/system/framework/framework-res.apk中,所以在编译过程中需要将其引进来。由此可有得出,我们在编译一个Android应用程序的资源的时候,至少会涉及到两个包,其中一个被引用的系统资源包,另外一个就是当前正在编译的应用程序资源包。
  • 3、收集资源文件
  • 4、将收集的资源添加到ResourceTable
  • 5、编译values类资源
  • 6、编译XML资源文件
  • 7、给资源生成资源ID:这个资源ID就是R文件里的声明的那些玩意。资源ID的生成是有套路的,这部分我把它放在后面的补充内容中去细说。
  • 8、根据资源ID生成资源索引表:也就是resources.arsc:
    android 资源那些事(一)编译 与 打包_第2张图片9、编译AndroidManifest.xml :
    10、生成R.java 文件

三、补充:

  • 1、在打包到apk里之前,会先把除了assets资源,res/raw文件资源以外的资源都编译成二进制格式,之所以要编译成二进制文件,原因无非两点:

    • 空间占用小,将大量的重复字符串构造在一个公共的地方(resources.arsc)
    • 解析速度快
  • 2、resources.arsc(资源索引表)负责记录所有资源信息,根据资源ID和设备信息,快速的匹配最合适的那个资源。R.java文件则负责记录各个资源ID常量。

  • 3、这个资源ID的生成是有套路的,id是一个32位数字,用十六进制来表示就是0XPPTTEEEE,PP为package id,也就是上面我们提到的ResTable_package数据结构中的id;TT位type id,也就是我们上面提到的ResTable_typeSpec数据结构中的id;EEEE为entry id,每个entry表示一个资源项,按照先后顺序自动排列。比如:0x7f010000,表示package id 就是0x7f,这个0x7f 是系统默认的,如果改这个值,可以在工程gradle 文件里设置,比如:

aaptOptions.additionalParameters '--PLUG-resoure-proguard', '--PLUG-resoure-id', '0x68'

在一些插件化处理资源冲突时,会有使用修改资源ID的方式,关于资源插件化,我后面会单独写一篇博客文章分享。

参考:
Android资源初探(一) 资源打包
Android应用程序资源的编译和打包过程分析

你可能感兴趣的:(Android开发,android)