主要是开发过程中的一点实践和思考,总结并记录如下。
一、如何选择性引入so库?
在引入一些第三方库的时候往往会提供多种so库给我们,我们应该都放进项目吗?
带着个这个问题先来了解一下ABI。
1、什么是ABI?
ABI 是 "Application Binary Interface"(应用程序二进制接口)的缩写,它定义了应用程序和操作系统或库之间的二进制接口规范。ABI定义了如何编码和处理数据、调用函数、传递参数以及执行其他与二进制接口相关的操作。它是一种用于确保不同二进制组件(如应用程序、库和操作系统)之间的互操作性的规范。
在 Android 中,ABI 是与 CPU 架构相关的,它定义了不同 CPU 架构上的二进制数据的排列和交互方式。Android 支持多种不同的 CPU 架构,例如 armeabi、armeabi-v7a、arm64-v8a、x86、x86_64 等,每种架构都有自己的 ABI 规范。
2、什么是ABI兼容性?
ARM 64-bit ABI Compatibility(ABI 兼容性)是指在 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-v7a的so也可以抛弃。如果保守做法可以保留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图片
②将svg转换为xml。通过这个网站,可以轻松的将svg转xml:
接着像普通图片那样使用即可。
2、能使用webp就使用webp
能使用webp就使用webp,webp相对传统的png、jpg的优势在于更小的文件大小、更好的图像质量、更好的透明度支持、更快的加载速度等。下面说明如何从蓝湖下载webp格式的图片:
①下载webp格式的图片
②蓝湖不支持压缩webp格式的文件,用tingpng网站继续压缩一下再使用。
3、png、jpg格式图片使用前一定要压缩
蓝湖上可以直接下载到压缩的png格式的图片,但我一般不喜欢用
还是喜欢用tingpng网站压缩一下再使用。
四、动态交付
简单描述就是用户要用到了才从后台下载,这种资源不打进Apk里。比如语言资源包,App支持多国语言,但一般用户一种语言就够用了。那哪些资源适合动态交付呢?
1、语言本地化资源
将语言的字符串资源作为独立的模块动态交付,而不是一次性下载所有的语言。
2、高分辨率图像或媒体
对于高分辨率图像、视频或音频资源,您可以将它们作为独立模块动态交付,以减小初始 APK 文件的大小。
3、不同设备配置
某些资源可能只在特定设备配置下使用,例如不同的屏幕分辨率、CPU 架构或屏幕密度,这种也能动态交付。
4、功能模块
某些应用的功能可能只有在用户需要时才会被使用,可以将这些功能模块化并按需交付,以减小初始安装包的大小。
5、插件
老生常谈的话题。
6、不常用的资源
如果应用包含大量不常用的资料或资源,例如历史数据、参考资料等,您可以将它们作为独立模块,用户可以在需要时进行下载。
总结:动态交付做起来要考虑的细节比较多,比如本地版本与远端版本差异等,交付模块的切割等。
参考
如有错误和不足欢迎批评和补充,谢谢!