一、背景
空的flutter项目编译生成Android apk包其体积约50MB左右,而空的原生Android项目编译生成的Android apk包其体积仅3.6MB左右,二者相差巨大!什么原因导致这一结果呢?
基本猜测:flutter生成的Android安装包apk中包含了大量flutter基础库代码。这些基础代码以什么样的形式存在apk中的呢?
为了解决以上疑惑故对flutter的Android包进行分析对比。
二、Android包结构
Android apk包本质是一个zip压缩包,可以将apk后缀改为zip并通过解压工具得到内部文件,一般包含如下文件:
- assets目录 存放需要打包到APK中的静态文件
- lib目录 程序依赖的Native库
- res目录 存放应用程序的资源
- META-INF目录 存放应用程序签名和证书的目录
- AndroidManifest.xml 应用程序的配置文件
- classes.dex dex可执行文件
- resources.arsc 资源配置文件
如原生apk包文件:
apk反编译工具
通过反编译工具可以进一步分析apk包内容,常用工具如下:
- apktool:编译和反编译apk,从apk中提取图片和布局资源。
- dex2jar:将可运行文件classes.dex反编译为jar源码文件。
- jdex-gui:查看aar源码文件 。
- apkanalyzer :Android Studio自带的apk分析工具。
三、原生APK与Flutter对比
一般apk分debug和release版本,故分别对这两种情况对比!
3.1 Debug包对比
flutter的debug apk包:
原生Android的debug apk包:
二者Debug包对比
总体体积(下载体积为apk应用商店内包实际大小):
名称 | 压缩包 | 解压文件 | 下载体积 |
---|---|---|---|
Android-app.apk | 3.6MB | 8.10 MB | 3MB |
flutter-app.apk | 49.5MB | 125 MB | 49.2MB |
diff(flutter-android) | 45.9MB | 116.9MB | 46.2MB |
通过对比发现,造成debug包体积差异过大的主要原因(解压文件对比):
lib下面添加了三种ABI的动态库,体积约94MB
assets目录下添加了一个kernel_blob.bin的二进制文件,体积约38MB
3.2 Release包对比
flutter的release apk包:包含三种ABI的.so库
Android的release apk包:
二者Release包对比
总体体积(下载体积为apk应用商店内包实际大小):
名称 | 压缩包 | 解压文件 | 下载体积 |
---|---|---|---|
android-release-app.apk | 3.2MB | 7.4 MB | 2.6MB |
flutter-release-app.apk | 15.7MB | 35.5 MB | 15.6MB |
diff(flutter-android) | 12.5MB | 28.1MB | 13.0MB |
通过对比发现,造成release包体积差异过大的主要原因(解压文件对比):
lib下面添加了三种ABI的动态库,体积约34.1MB
assets目录下文件,体积约1MB
四、flutter生成不同ABI动态库的apk包
通过剔除不必要的ABI动态库.so包,从而减少apk包体积大小。
4.1 ABI简介
不同的 Android 设备使用不同的 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口 (ABI)。 android支持的 ABI如下:
ABI | 适用设备 | 市场占有率 | 适配厂家 |
---|---|---|---|
armeabi-v7a | 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它。 | 一些老旧的手机 | 淘宝 |
arm64-v8a | 第8代、64位ARM处理器 | 目前主流版本 | 微信 |
armeabi | 第5代、第6代的ARM处理器,早期的手机用的比较多 | 较少 | 支付宝、手Q、旧版微信 |
x86 | 平板、模拟器用得比较多 | 很少 | |
x86_64 | 64位的平板 | 很少 |
高版本的arm架构会兼容低版本的arm架构,一般厂商只会选定一个cpu架构进行适配,为了减少apk包大小我们可以选定armeabi-v7a或者arm64-v8a即可。
4.2 flutter打不同ABI的apk包
通过下面的命令,可以生成不同ABI的apk包,该命令默认release并开启压缩:
flutter build apk --split-per-abi
包大小列表:
打包含单独ABI的release apk包平均大小6MB左右,可以有效的降低包体大小。
五、总结
初始项目的flutter打apk包情况如下:
- debug环境:包体较大,因为没有压缩且包含多个ABI的so文件以及资源文件,包大小为50MB左右。
- release环境:包体较小,因为开启了压缩且仅打单个CPU架构的so文件,包大小可以降低到6MB左右。