Android 开发阶段控制安装包的体积大小

911 阅读8分钟

主要是开发过程中的一点实践和思考,总结并记录如下。

一、如何选择性引入so库?

在引入一些第三方库的时候往往会提供多种so库给我们,我们应该都放进项目吗?

带着个这个问题先来了解一下ABI。

1、什么是ABI?

ABI"Application Binary Interface"(应用程序二进制接口)的缩写,它定义了应用程序和操作系统或库之间的二进制接口规范。ABI定义了如何编码和处理数据、调用函数、传递参数以及执行其他与二进制接口相关的操作。它是一种用于确保不同二进制组件(如应用程序、库和操作系统)之间的互操作性的规范。

Android 中,ABI 是与 CPU 架构相关的,它定义了不同 CPU 架构上的二进制数据的排列和交互方式。Android 支持多种不同的 CPU 架构,例如 armeabiarmeabi-v7aarm64-v8ax86x86_64 等,每种架构都有自己的 ABI 规范。

2、什么是ABI兼容性?

ARM 64-bit ABI CompatibilityABI 兼容性)是指在 64 位 ARM 架构的设备上运行 32 位 ARM 应用程序的能力。具体来说,它允许 64 位 ARM 设备(如 arm64-v8a 架构)能够执行采用 32 位 ARM ABI(如 armeabi-v7a 架构)的应用程序,而不需要修改应用程序的二进制代码。这是通过 Android 运行时系统的机制来实现的。

为了实现 ABI 兼容性,Android 在 64 位设备上提供了一种称为 "ARM 32-bit ABI Compatibility" 的特殊层,它可以运行 32 位应用程序,并为这些应用程序提供必要的支持,以确保它们能够在 64 位环境中正确执行。这一机制是为了确保旧的 32 位应用程序能够在新的 64 位硬件上运行,同时允许开发者逐步迁移到更现代的 64 位应用程序。

3、arm64-v8a, armeabi-v7a, armeabi

市面上的机型基本都是arm64-v8a, armeabi-v7a, armeabi这三种CPU架构,先了解一下这三种架构以及它们的区别:

arm64-v8a:

  • 架构名称:ARM 64-bit(AArch64)
  • CPU 支持:64 位 ARM 处理器(例如 Qualcomm Snapdragon 810、Samsung Exynos 7420 等)
  • 特点:arm64-v8a 是 64 位架构,提供更大的寄存器和内存地址空间,更好的性能和更高的内存支持。它通常用于最新的高端 Android 设备。

armeabi-v7a:

  • 架构名称:ARM 32-bit(ARMv7-A)
  • CPU 支持:32 位 ARM 处理器,包括 ARM Cortex-A 系列和一些旧的 ARM Cortex-R/M 系列
  • 特点:armeabi-v7a 是 32 位架构,兼容性较好,适用于大多数 Android 设备。它支持多核心处理器和优化指令集,提供较好的性能。

armeabi:

  • 架构名称:ARM 32-bit(ARMv5TE)
  • CPU 支持:旧版的 32 位 ARM 处理器
  • 特点:armeabi 是一个较旧的架构,现在已不常见。它的性能相对较低,不再是主流的 Android 架构。

区别:

  • 架构类型:arm64-v8a 是 64 位架构,而 armeabi-v7a 和 armeabi 都是 32 位架构。
  • CPU 兼容性:arm64-v8a 仅支持 64 位 ARM 处理器,而 armeabi-v7a 和 armeabi 支持不同的 32 位 ARM 处理器。Android通过中间层使arm64-v8a具备了兼容32位的能力。
  • 性能:arm64-v8a 提供更好的性能和内存支持,尤其适用于高端设备。armeabi-v7a 在中端设备上表现良好,而 armeabi 是相对较低性能的旧架构。
  • 兼容性:为了兼容不同的设备,应用程序通常会提供多个 ABI(Application Binary Interface)版本,以支持不同的 CPU 架构。

4、大厂APP兼容哪些CPU架构

通过反编译一些大厂的App,看看它们都支持哪些ABI,于是得到了下面的表格:

反编译的App支持的ABI
美团arm64-v8a
微信arm64-v8a
网易云音乐arm64-v8a
淘宝armeabi-v7a、arm64-v8a
抖音armeabi-v7a
知乎armeabi-v7a

armeabi架构已经是非常老旧的手机了,大家都不支持很正常。arm64-v8a因为有Android的兼容层可以兼容32位的armeabi-v7a,所以其实armeabi-v7aso也可以抛弃。如果保守做法可以保留armeabi-v7a、arm64-v8a,但是多一类so库,包体积会增大挺多。至于只支持armeabi-v7a的App,多半是历史遗留问题,在不久的将来不支持64位处理器的App将不会允许上架,这样又会多很多适配工作。

5、开发阶段如何选择

前段时间接入支付功能,上游提供SDK的时候提供了arm64-v8a, armeabi-v7a, armeabi3个平台的so库,最后我们只放了arm64-v8a进来。既然大厂都只支持arm64-v8a,我们有必要比它们还保守吗?哈哈哈!

ndk {
    abiFilters 'arm64-v8a'
}

当然,如果开发的是定制的工业平板的App等,那还是要根据具体CPU类型来。

二、混淆与清除无用资源

1、minifyEnabled与shrinkResources

minifyEnabled通过重命名、删除和优化代码来增加应用程序安全性和减小应用程序大小。

shrinkResources用于在构建期间删除未使用的资源文件以减小最终 APK 文件的大小。

所以这二个都可以减少包体积大小。

2、如何开启minifyEnabled与shrinkResources

minifyEnabled可以在每个module的build.gradle中配置,如果在app的build.gradle中配置为true,表示整个App需要混淆,如果又在子module中单独配置为false则该子模块不混淆。不能混淆的记得keep

shrinkResources只能在app的build.gradle中开启,在子module中开启会报错。

示例代码如下:

android {
    buildTypes {
        release {
           shrinkResources true // 启用资源缩减
           minifyEnabled true    // 启用代码混淆
           proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

三、图片资源

图片一直都占包体积的很大一部分,所以在引入图片资源时一定要谨慎。

1、能使用svg就使用svg

svg一般较小且可以无损缩放,下面说明如何从蓝湖下载一张svg图片并转换为xml:

①从蓝湖下载一张黑白svg图片

image.png

②将svg转换为xml。通过这个网站,可以轻松的将svgxml

image.png

接着像普通图片那样使用即可。

2、能使用webp就使用webp

能使用webp就使用webpwebp相对传统的pngjpg的优势在于更小的文件大小、更好的图像质量、更好的透明度支持、更快的加载速度等。下面说明如何从蓝湖下载webp格式的图片:

①下载webp格式的图片

image.png

②蓝湖不支持压缩webp格式的文件,用tingpng网站继续压缩一下再使用。

3、png、jpg格式图片使用前一定要压缩

蓝湖上可以直接下载到压缩的png格式的图片,但我一般不喜欢用

image.png

还是喜欢用tingpng网站压缩一下再使用。

四、动态交付

简单描述就是用户要用到了才从后台下载,这种资源不打进Apk里。比如语言资源包,App支持多国语言,但一般用户一种语言就够用了。那哪些资源适合动态交付呢?

1、语言本地化资源

将语言的字符串资源作为独立的模块动态交付,而不是一次性下载所有的语言。

2、高分辨率图像或媒体

对于高分辨率图像、视频或音频资源,您可以将它们作为独立模块动态交付,以减小初始 APK 文件的大小。

3、不同设备配置

某些资源可能只在特定设备配置下使用,例如不同的屏幕分辨率、CPU 架构或屏幕密度,这种也能动态交付。

4、功能模块

某些应用的功能可能只有在用户需要时才会被使用,可以将这些功能模块化并按需交付,以减小初始安装包的大小。

5、插件

老生常谈的话题。

6、不常用的资源

如果应用包含大量不常用的资料或资源,例如历史数据、参考资料等,您可以将它们作为独立模块,用户可以在需要时进行下载。

总结:动态交付做起来要考虑的细节比较多,比如本地版本与远端版本差异等,交付模块的切割等。

参考

支持 64 位架构

如有错误和不足欢迎批评和补充,谢谢!