apk 瘦身系列①:解剖 apk

作者: rain 分类: 移动 发布时间: 2016-03-09 19:03 6 条评论

如果要问码农们他们开发的应用的大小。我敢说大部分码农都会查看 Android studio 或者其他 build 工具生成的 APK 文件所占用的磁盘空间大小。这是一个很直接的答案,也算是一个正确答案。但是如果换个问题,则又当如何呢?比如如下问题:
– 当把你的应用安装到用户手机上的时候会占用多少空间?
– 用户为了下载并安装你的应用需要使用多少流量?
– 已经安装了你的应用,在升级的时候需要消耗多少流量?
– 运行你的应用需要使用多少手机内存?

作为合格的开发者,我们可能大部分都使用当前高端的手机开发测试应用,所以你可能说:没必要浪费时间来给 apk 瘦身吧,现在的手机内存和存储空间都这么大! 注意:并不是所有的设备都是高端设备,并不是每个人都有很多流量。

当前世界上还有很多地方并没有WIFI热点,没下载一个字节的数据他们都要付出不少流量费。还记得天价流量费的故事吗?

并且有些设备并没有足够的内部存储空间来安装很多应用,对于这些用户来说,是否要安装一个应用都需要纠结半天。谁也没法保证这些用户是否就是你下一个千万级用户之一,所以来说尽可能的给你的应用瘦身吧! 只有好处没有坏处!人人都可以从中受益!

考虑到安卓所面临的不同设备满天飞的情况,肯定没法选择一个适合所有情况的最佳方案。有时候牺牲初始安装包大小可以加速后续的升级。有时候,在 apk 中使用未压缩的文件可以减少最终应用在用户设备上所占用的空间。在后续的文章中会尽可能的阐述这些情况。至于你使用哪种情况来打包你的应用,就取决于你所面对的具体情况了。

本系列文章不会涉及太多运行时所占用内存的问题。文章中讲到的瘦身方法可能对运行时内存会有好的或者坏的影响,遇到这种情况的时候,会尽可能的说清楚具体的影响。但是,具体在你的应用中有和影响,还需要你自己来测量。请记住:#性能很重要!

apk 中都包含什么?

在了解如何瘦身之前,需要先知道一个 apk 中都包含哪些组成部分。apk 文件其实就是一个 zip 格式的压缩文件,只不过扩展名为 apk 而已。通常情况下一个 apk 文件中会包含如下内容:

classes.dex

这里面是编译后的 dex 格式的代码。如果你的应用中函数数目超过了 65536,则需要使用 multidex ,这种情况下会有多少 dex 文件。从安卓 5.0 开始,新的 ART 运行框架在安装应用的时候会把这些 dex 文件预处理为 OAT 文件,并放到设备的数据区域中。在第二部分中会详细介绍如何减少代码所占用的空间。

res/

这个目录里面大部分都是 XML 资源(比如 布局文件、菜单定义等)和 drawables 资源(比如 png 图片 等),这些资源可以有不同的限定符(比如 mdpi、sw600dp、large、en 等)。值得注意的是,该目录下的所有的 xml 文件都被转换为二进制格式来减少占用的空间,所有 apk 中的 xml 文件是没法直接用文本编辑器查看其原始内容的。

在后续介绍中会介绍如何针对资源文件瘦身。

resources.arsc

有些资源和资源标示符被编译到该文件中。这些文件一般都不使用压缩格式,这样在运行的时候效率会更高。可能你认为压缩这个文件,可以减少一些 apk 尺寸。其实这是没必要的,原因有两点:1、Play 商店在下载应用的时候,会压缩传输数据;2、在 apk 中压缩这个文件会浪费系统资源并影响性能。

后续文章中会介绍一种有意义的减少该文件大小的方法。

AndroidManifest.xml

和其他 xml 文件一个,该文件也是二进制文件。 Play 商店使用该文件中的一些信息来判断应用是否可以安装到一个设备上,例如检测兼容的屏幕大小和屏幕密度,以及兼容的硬件。如果你想检测一个 apk 的这些属性,可以通过如下命令:

$ aapt dump badging your_app.apk

libs/

该目录中包含各种原生库(.so 文件),每个库会放到对应的 cpu 架构目录下,例如 x86, x86_64, armeabi-v7a 等。通常情况下,这里面的 so 库都会在安装应用的时候复制到你应用对应的 /data 数据区中。由于 so 库并不会改变,这样就有两份 so 文件存在用户设备上,会浪费用户的磁盘空间。后续文章中会介绍一种优化的方式。

assets/

这里面包含哪些无法放到 res/ 目录下的各种非安卓类型的资源文件。大部分情况下这里面会放置自定义字体、应用数据文件 等。

META-INF/

签名的 apk 会包含这个目录,里面包含了 apk 中的所有文件的签名。在安装应用的时候,会验证每个文件加压缩后的签名。

这样就导致一些问题。由于 zip 文件中的每个文件都是单独保存的,这意味着你可以修改单个文件的压缩等级而不需要重新签名。但是,如果在签名后,你删除 apk 中的任意内容都会导致签名校验失败。

zipalign 工具是在 build 过程中最后一步的。如果你手工的修改了文件的内容,则在使用 zipalign 之前需要重新签名 apk。

使用 Zopfli 来重新压缩 apk 文件

使用更高级的压缩算法可以减少 apk 的尺寸。 Zipalign 工具支持使用 Zopfli (谷歌开发的一种压缩算法)来重新压缩 apk 中的内容。使用如下的 zipalign 命令即可把 Android Studio 生成的 apk 文件从新压缩一下:

$ zipalign -z 4 infile.apk outfile.apk

也可以之间把如下内容添加到你的 build.gradle 文件中来自动压缩:

注意: 使用 Zopfli 压缩文件可能会需要一些时间,但是大部分情况下都会让你的 apk 变得更少一些的。

本系列文章原文:https://medium.com/google-developers/smallerapk-part-1-anatomy-of-an-apk-da83c25e7003#.9orrry7ig
更新: 在今年的 Google IO大会上也针对此有个专门的演讲:Lean and Fast: Putting Your App on a Diet http://v.youku.com/v_show/id_XMTU3ODE3NjYxMg==.html

本文出自 云在千峰,转载时请注明出处及相应链接。

本文永久链接: http://blog.chengyunfeng.com/?p=879

Ɣ回顶部