背景与问题
随着客户端接入业务的日益增加和集成功能的日益丰富,客户端APK安装包也随之增大。
过大的安装包会带来的不利影响如下:
1.对外,增加用户下载时的流量消耗,延长应用安装时间,降低用户体验。
2.对内,增加了企业“打包-上线-发布”流程消耗的时间成本,同时也会影响到开发时的单次构建效率。
解决方案
APK瘦身
利用AS对APK包进行分析,结果如图:
由图可知,APK大小中占比重较大的主要为lib,resource(res,assets),dex,因此APK瘦身主要针对这三者进行处理。本篇就先从lib入手。
1. lib目录优化分析
由图可知,当前lib目录下包含armeabi、armeabi-v7a,x86三个子目录,它们分别代表三种ABI,并包含支持该ABI的so库文件。
查看三个子目录,发现三个ABI目录下包含同名so文件,armeabi-v7a额外包含一些so文件,那么,这些同名so文件是否可以只保留一份?如何选择?
同时,对支付宝、微信等大厂的APK进行解包可以看到,可以看到这些大厂的APK中,lib目录下是只保留一份armeabi的。
2.Android SO与ABI
ABI简介
- Android设备可支持ARMv5,ARMv7,X86,ARMv8,X86_64等多种CPU架构
- 每种CPU架构都定义一种 ABI(Application Binary Interface,应用二进制接口),ABI定义了其所对应的CPU架构能够执行的二进制文件(如.so文件)的格式规范。
CPU | ARMv5 | ARMv7 | x86 | MIPS | ARMv8 | MIPS64 | x86_64 |
---|---|---|---|---|---|---|---|
ABI | armeabi | armeabi-v7a | x86 | mips | armeabi-v8a | mips64 | x86-64 |
SO简介
- so(shared object,共享库)是机器可以直接运行的二进制代码,是Android上的动态链接库,类似于Windows上的dll.
每一个Android应用所支持的ABI是由其APK提供的.so文件决定的. 例如:
lib
|
├── armeabi
│ └── libmath.so
├── armeabi-v7a
│ └── libmath.so
├── mips
│ └── libmath.so
└── x86
└── libmath.so说明该应用所支持的ABI为armeabi, armeabi-v7a, mips, 和x86。
Android系统的ABI支持
Android可以在运行期间确定当前系统所支持的ABI,这是由系统编译时的具体参数指定的:
primary ABI(主ABI):对应当前系统中使用的机器码类型
secondary ABI(副ABI):表示当前系统支持的其他ABI类型
上图可知,该设备的primary ABI是arm64-v8a许多手机支持不止一个ABI,比如,一个基于ARMv7的设备会将armeabi-v7a定义为primary ABI,armeabi作为secondary ABI,意味着这台机器同时支持armeabi-v7a和armeabi
- X86手机存在一个Binary Translator(二进制转换中间层) houdini. 它会在运行期间动态的读取arm指令并将之转换为x86指令去执行。
- 许多基于x86的设备也可以运行armeabi-v7a和armeabi的so,对于这些机器,primary ABI是x86,secondary ABI则是armeabi-v7a.
APK安装时对so的选择过程
应用安装时,Package Manager会扫描整个apk文件,寻找符合下面文件路径格式的动态链接库:
lib//lib.so如果在apk内并没有找到适合当前机器primary-abi的so,Package Manager会尝试寻找适合secondary-abi的so文件: lib//lib.so
如果找到了合适的so文件,包管理器会将该ABI文件夹下所有so库全部拷贝至应用的data目录下: data/data//lib/
- 运行时找不到so,则会报Java.lang.UnsatisfiedLinkError问题
- 安装APK时PMS只负责拷so,至于这个so是何种ABI是不感知的。
- 支持armeabi-v7a的设备同样支持armeabi的so文件,反之不行。
3.SO精简处理方案
通过对使用用户中各ABI的分布对比,armeabi和x86占比极小,所以选择不考虑保留armeabi和x86,只保留armeabi-v7a。
通过修改gradle文件,在buildType模块增加对打包时ABI的指定,如下:
ndk { abiFilters "armeabi" }
经过so的精简,APK大小减小了7M+,下一步会继续研究下对资源文件和dex文件的精简。