通过重新压缩其内容来减小 APK 大小

Posted

技术标签:

【中文标题】通过重新压缩其内容来减小 APK 大小【英文标题】:Reducing APK size by re-zipping its content 【发布时间】:2014-10-15 00:26:25 【问题描述】:

我有一个相当大的 apk 文件,我正在尝试减小它的大小。 已经使用了所有常用技术,例如 Proguard 和图像压缩。尽管如此,apk 还是相当大的——大约 25mb。

Wikipedia 说:

APK 文件是一种存档文件,特别是 zip 格式 基于 JAR 文件格式的包,以 .apk 作为文件名 扩展名。

我最近注意到,如果我将 apk(android Studio 的工件输出)解压缩,使用 7-Zip 重新压缩并对其进行签名,那么大小会神奇地减少 2.5mb(约 22.5mb)。我可以毫无问题地将它上传到 Play、安装和运行它。

这是我的问题:

在解压缩和重新压缩过程中是否有任何数据被擦除? 如果,为什么 aapt(Android Studio 使用的那个)打包文件 以如此低效的方式? 如果,正在擦除哪些数据(请张贴一些链接 可以阅读更多相关信息)?如果出现什么问题 我会用这个方法吗?

谢谢!


编辑 [5/13/2015]:

压缩 APK 内容对我来说效果很好。但是,我必须对原始资源(通常放在 res/raw 下)保持谨慎。例如,使用压缩资源作为参数调用 Resources#openRawResourceFd 将结束并出现以下异常:

java.io.FileNotFoundException: 这个文件不能作为文件打开 描述符;它可能被压缩了

因此,请记住从压缩中排除原始资源。

【问题讨论】:

1.根据放入存档的实际文件,不同的压缩/压缩算法可能或多或少有效。 2. 为什么您如此担心可以减少 10% 的 APK 文件大小?这并不是一个巨大的减少——例如,Facebook 应用程序接近 26MB 3。如果您担心数据/组件被擦除,为什么不自己测试一下呢?只需使用两种不同的方法,解压缩 apk 文件的两个变体,然后对每个文件运行文件比较。 @Squonk 3 - 我已经验证没有文件被更改/删除。我更关心的是(可能的)元数据注入,后来被 Android 在最终用户的设备上使用。 @AlexLipov :从字面上看,APK 是一个 ZIP 文件——我从未见过相反的证据,也没有任何“隐藏”的元数据。您已经测试了您的理论 - 您能够上传到 Google Play 并毫无问题地安装和运行。我已经发布了一些应用程序并相信我 - 如果 Google 不喜欢您上传的内容,那么它会在那时失败。能够安装和运行基本上可以达成交易——这是否是一件好事是另一回事。压缩技术有许可/知识产权问题等的历史。也许 aapt 只是采用一种简单的方法。 @FrankN.Stein :当然,我明白你的意思,但是在 APK 大小的限制范围内,即 25MB 减少 2.5MB,花费额外的时间/精力似乎没有什么意义.在您的示例中,如果您的下一个 APK 从 54MB 增长到 56MB 或 60MB,该怎么办?在这一点上,无论如何您都必须查看扩展文件。 如果您打算使用自己的工具来创建 apk 文件,请确保在压缩并签名后运行 zipalign - 不这样做可能不会导致应用程序无法运行,但可能会使结果在运行时需要更多的内存。 【参考方案1】:

    在创建 apk 时,仅使用“V1(Jar Signature)”选项对 apk 进行签名。这是在 Android Studio 中生成签名 apk 时对话框中的一个选项。阅读此处的警告,https://developer.android.com/studio/command-line/zipalign。

    将 apk 解压到一个文件夹,例如 app-release。

    转到文件夹 app-release 中的命令提示符。

    然后重新压缩:

    "C:\Program Files\7-Zip\7z.exe" a -tzip -mx9 -r app-release.zip *.*

    然后对齐:

    "C:\Users\Administrator\AppData\Local\Android\Sdk\build-tools\30.0.0\zipalign.exe" -f -v 4 app-release.zip app-release.apk

    然后验证对齐:

    "C:\Users\Administrator\AppData\Local\Android\Sdk\build-tools\30.0.0\zipalign.exe" -c -v 4 app-release.apk

【讨论】:

【参考方案2】:

假设您强制 7zip 使用其 zip 兼容模式 (-tzip),那么这是一个完全有效的操作(尽管正如 @CommonsWare 所指出的那样,您极有可能让自己接受一些错误的某些手机​​上的 zip 解包程序)。

您能够缩小尺寸的原因有两个:

7zip 具有更好的压缩器,它在压缩时使用更多 CPU 来提供完美兼容但压缩程度更高的表示 传统上用于对 Android 文件进行压缩/打包的 aapt 有很长的文件类型列表(例如 jpg、png、mp3),它根本不会尝试压缩,因为这些文件类型已经有了内部压缩。即便如此,通过将它们压缩到 apk 文件中通常可以获得几个百分点的收益

【讨论】:

【参考方案3】:

我可以毫无问题地将它上传到 Play、安装和运行它。

仅在您尝试过的设备上。例如,我怀疑您没有尝试使用 API 级别 1 设备。

在解压缩和重新压缩过程中是否有任何数据被擦除?

我们无法回答这个问题。唯一能回答这个问题的人是你,因为你是执行特定“解压缩和重新压缩过程”的人。您应该能够分析您的两个 ZIP 文件并查看差异所在,例如某些文件类型的压缩率更高、文件因运行“重新压缩过程”的方式而丢失等。

一般来说,唯一应该丢失的是任何 zipalign-ing,如果您没有自己重新应用的话。

如果不是,为什么 aapt(Android Studio 使用的那个)以如此低效的方式打包文件?

尺寸不是唯一的考虑因素。访问速度是另一个问题,因为很多东西(例如,资源、资产)都保存在 APK 文件中,并根据需要随时从那里读出。解压缩逻辑的内存消耗是另一个考虑因素。

Android 设备,尤其是早期的设备,有很多限制,磁盘空间只是其中之一。尽管随着硬件的进步,其中一些限制已经放松,但构建工具致力于向后兼容——例如,您现在应该能够编写一个可以在 API 1 级设备上运行的应用程序。这限制了工具如何随时间改变。

如果我使用这种方法会出现什么问题?

您的应用可能无法在 Android 设备上运行,这些设备的运行时设置是对使用的 APK ZIP 压缩算法做出某些假设。理想情况下,您的应用程序在任何地方都可以正常运行。至少,您希望在您支持的每个 API 级别上测试您的应用 - 较旧的 API 级别可能更有可能“偷工减料”并假设您的方法将失效。

【讨论】:

以上是关于通过重新压缩其内容来减小 APK 大小的主要内容,如果未能解决你的问题,请参考以下文章

MediaMuxer 视频文件大小减小(重新压缩,降低分辨率)

Android开发——减小APK大小

如何减小包装尺寸

从命令行构建 APK 后使用 zopfli 重新压缩运行 zipalign 以使其更小

怎么给修改后的apk重新签名?

zip -9 压缩不会减小文件大小