Andorid资源瘦身去重丶图片压缩丶混淆插件(3)
前介
一个 Apk
主要分为 res
丶 dex
丶 META-INF
丶 AndroidManifest.xml
丶 resources.arsc
组成(对应文件作用看下方表格)。
从图片可以看到一个项目的 res
占很大一部分内存,其次就是 dex
文件。所以优化 Apk
的体积就应该从 res
丶 dex
出发。
昵称 | 介绍 |
---|---|
res |
Apk 资源,代码中对应的 res 目录下的所有通过 AAPT 编译的产物。 |
dex | 所有的 Class 文件的归宿 |
META-INF | 报错通过 V1 签名的签名信息 |
AndroidManifest.xml | 通过 AAPT 优化编译的清单文件 |
resources.arsc | 通过 AAPT 编译资源生成的产物,主要存放资源 ID (R 类生成的 ID )和 res 目录下的资源文件对应关系 |
定位目标
前面都是一堆准备工作,我们来明确目标。最终要完成在 APK
构建过程中,将 res
目录下所有的图片进行 去重
丶 压缩处理
丶 混淆
。
寻找合适的Task
确定了目标后,我们就知道优化的目标在 Apk
的 res
目录下所有的资源文件,由于存在对 res
目录的文件进行 改
(混淆) 丶 删
(去重) 的情况,在修改的同时还需要修改 resources.arsc
文件。因为前面讲了,这个文件中存着一份 ID
和 资源的映射关系。
这里大家是不是就能衍生出换肤的难点在哪了吧?要保证新生成的皮肤
resources.arsc
的ID
要和宿主的ID
保持一致。这样代码中才能正确的通过ID
找资源,其实R
也是AAPT
插件生成的哦。学完这篇我相信大家也能做一款属于自己的换肤插件。
接下来思路就清晰了。我的第一想法是在生成 resources.arsc
前,优化 res
目录下面所有的图片。这样就规避掉了
修改 resources.arsc
的难点。
通过第一章代码我还真找到了一个 mergeDebugResources
的 Task
它的作用就是合并资源,包含依赖的资源(如何找呢?通过我上一篇分享的文章,看每个 Task
的输入路径)。但是回头一想,这样就不能做去重复的功能了,因为我如果删除重复的资源,代码引用并不知道啊!(因为我的删除重复资源是相同文件,并不是简单昵称相同)。
到这里,我们分析结束,只能在生成 resources.arsc
之后做优化操作,并修改 resources.arsc
文件了。哪 resources.arsc
是多久生成的呢?我们来看下面的一张图。
AAPT
来打包 res
资源文件,生成 R.java
、resources.arsc
和 res
文件。我们只需有找到一个执行 AAPT
的 Task
在这个 Task
之后做操作。
其实我当时中间有另外一种想法,能不能自己改造一个
aapt
呢?查阅资料思路是可行的,但是过于复杂和兼容性不强(主要需要改C
代码,我不会),有兴趣可以参考
接下来我们应该找一个执行 AAPT
的 TASK
,接着用我前面讲的输出所有 Task
的输入和输出路径,寻找产物有 resources.arsc
的 Task
。
我在
build
目录中找了半天resources.arsc
文件,但是死活找不到。
最后发现了一个 processDebugResources
的 Task
。
- 调用
aapt
生成项目和所有aar
依赖的R.java
, 输出到app/build/generated/source/r/debug
目录 - 生成资源索引文件
app/build/intermediates/res/resources-debug.ap_
- 把符号表输出到
app/build/intermediates/symbols/debug/R.txt
这个 Task
的产物是 resources-debug.ap_
(就是个 zip
文件)解压下就可以所有的数据了。
终于看到 resources.arsc
并且还附带了 res
中所有的资源了。
没事干你整个压缩包干嘛呀,害的我找了好久。
最后只需要在 processDebugResources
Task
之后,解压 resources-debug.ap_
文件,遍历 res
下所有的图片进行去重丶压缩丶混淆丶修改 resources.arsc
,从新压缩改造内容,替换 resources-debug.ap_
文件即可。
源代码
QOptimize
插件是一款,在 Apk
编译期间对 Apk
进行体积优化的一款插件。