APK瘦身 - 移除无用文件

https://wx4.sinaimg.cn/mw690/c0755e72gy1ff8eyorepbj21jk0rcgvf.jpg

有两种方式来移除你的应用中那些不需要的,但由于它在你的项目文件夹或者依赖中因此被打包进APK的资源。一种方式是依赖我们上一个章节讨论的压缩。除了移除掉无用的代码,它也会分析有哪些资源是真正被使用并且移除从没有在你的布局、图片、代码等地方出现过的资源。为了开启资源压缩,在你的release构建类型中添加如下一行(shrinkResources true

就像移除代码一样,自动化工具有时对于那些资源是正真被需要的会有判断误差。你可以通过使用tools:keep属性来告诉构建系统你想保留的资源。与混淆的配置文件中能够列出需要保留的类和方法类似,你

可以通过在你项目中的任何<resources>变迁中添加,或者为压缩规则创建一个单独的文件。

res/raw/keep.xml

You can also specify tools:discard to deliberately remove resources that were kept:

你也可以指定tools:discard标签来故意移除被保留的资源。

res/raw/keep.xml

你可以通过查看日志文件以及在 tools site上查看关于安全模式和严格模式的意义来了解更多关于调试资源压缩的事项。

当然,时刻保持你项目的文件夹整洁是好的习惯,因此如果有任何你知道将不会被使用的历史资源,你应该直接删除这些文件。

通过ResConfigs来移除无用的配置

许多库会伴随着被翻译成许多语言的字符串资源。例如,Android 的Support库和Google Play服务就是这种情况。你甚至可能在你研发的应用上做了翻译,但是你不准备将这些语言发布到市场上。你可以使用resConfig选项来限制最终被打包进APK中的语言配置。

build.gradle

上面的配置会移除和这两种语言配置无关的资源。

请注意当与屏幕密度一起使用时,resConfigs具有其它的语义,最好使用第四部分中的的拆分来代替。在第五部分中有关于密度的resConfig的使用实例。

resources.arsc文件的稀疏配置

这个章节我将要讨论的问题通常只针对大型的应用,带有数以千计的字符串、样式或者其它带有id并且将被打包进resources.arsc文件的资源。

如果你注意到这个文件占据着你应用非常大的空间,这可能就意味着你有太多的稀疏配置,让我通过

例如你有在默认的配置文件夹(values/string.xml)中定义了5个基础的字符串。这些字符串它们本身会被定义在一个字符串池中,然而资源文件的另外一个部分也包含了一个又指向这些字符串的资源配置所组成。为了更好的解释,下面是一个简单的resources.arsc文件的可能样子:

现在假设你为你的应用添加了一个只在API21+上工作的新特性。这个特性需要在某个时机显示不同的提示信息,所以你决定在values-v21/strings.xml 文件中覆盖一个字符串然后重新编译应用。

你会认为你只向字符串池添加了一个新的字符串和一个为新创建的v21配置的字符串指针。非常不幸,这并不是resources.arsc文件格式的工作方式。相反,你会看到的是如下的格式:

最终结果就是,每种配置(-v21,-land 或者甚至是-en-land-v21)在每个资源的位置上都为指针预留了空间。时机指针可能为空,这就意味着在这种配置下没有对应的值。一个空的指针也会占用4字节。

像我在开头提出的一样,这里可能节约的空间大部分取决于你的应用中有多少字符串(或者其它类型的资源)。例如上面的例子,在-v21配置中开始的占用4*4字节,这就意味着有16字节由于空的条目被浪费(我们实际上需要的指针占用4字节)。

然后,举个更加普遍的例子,如果一个定义了3500个字符串的应用,并且具有单独的配置,其中一个字符串被翻译成了50种语言(所以它会有例如values-en-land, -pl-land, -de-land, *-fr-land…等文件夹),它会浪费:

4 bytes * 3500 null entries * 50 languages = 700 kilobytes

这70万字节能够通过减少一个字符串来被节省,并且我也见过应用通过移动少至3个资源以减少配置数量,从而节省了超过2.5MB。

因为你在一个单独的配置中第一次放置了一个资源。这通常意味着你需要它并且它也通常都是在Android中处理起来最合适的方式。但是如果你能确定因为减少一个或者几个资源能够节省你很多的空间,你可能需要考虑找到一个合适的方法来避免通过这种方式使用这几个资源。

另一种方式虽然不太优雅,就是我们可以在代码中来针对不同的特性进行资源的切换。 例如,在values / strings.xml中,可以有两个字符串:string / my_feature和string / my_feature_land,然后根据当前屏幕方向在运行时选择正确的字符串。

We’ve open sourced a tool that can help you find sparse resource configurations and identify which resources contribute to your resources.arsc bloat. It’s called ArscBlamer and can be found here:

我们开源了一个能够帮助你找到稀少资源配置的工具,并且这个工具能够指出哪些资源有助于resources.arsc文件。它叫做ArscBlamer,可以在这里找到:

image

你需要安装Bazel 来编译ArscBlamer,你可以使用下面的命令编译,然后运行:

image

然后,打开通过类似如Google Sheet等编辑器打开cvs文件,然后通过Null 条目降序排列。 配置中有最多空条目的配置可能就是需要被裁减的。右侧的资源名称(Keys)将是你可以删除的资源名称(Keys)。

让我知道这种技术是否适用于您的应用程序,以及如何减少resources.arsc的大小!


image           image
章节列表