21、APK分析:APK Analyzer使用、分析APK组成、减少APK体积
APK 分析,说白了就是给你的安装包做一次「体检」。我刚开始做 Android 开发那会儿,APK 动不动就 50MB、80MB,用户下载意愿直线下降。后来 Google 推出了 APK Analyzer,这工具简直就是救星。今天我就带你把它用透。
APK Analyzer 怎么打开?
有两种方式进入这个工具:
- 拖拽大法:直接把 .apk 或 .aab 文件拖到 Android Studio 的编辑器区域
- 菜单路径:Build → Analyze APK… 然后选择你的 APK 文件
我个人习惯用拖拽,快。打开后你会看到一个分栏界面,左边是文件树,右边是详细信息。
核心功能一览:
- 查看 APK 内所有文件的原始大小和下载大小
- 分析 DEX 文件中的类、方法、字段数量
- 查看资源文件的压缩情况
- 对比两个 APK 版本的差异
APK 内部到底长什么样?
一个 APK 其实是个 ZIP 压缩包。解压后你会看到这些核心部件:
| 文件/目录 | 说明 | 体积占比(典型) |
|---|---|---|
| classes.dex | 编译后的 Java/Kotlin 字节码 | 30% - 50% |
| resources.arsc | 编译后的资源索引表 | 5% - 15% |
| res/ | 图片、布局、字符串等资源 | 20% - 40% |
| lib/ | Native 库(.so 文件) | 10% - 30% |
| META-INF/ | 签名信息、清单文件 | 1% - 3% |
| AndroidManifest.xml | 应用配置清单 | < 1% |
嗯,这里要注意:下载大小和原始大小是两个概念。Google Play 统计的是下载大小,也就是 ZIP 压缩后的体积。APK Analyzer 会同时显示这两个值,方便你判断哪些文件压缩率低、值得优化。
如何用 APK Analyzer 揪出体积「元凶」?
打开 APK Analyzer 后,我一般按这个顺序排查:
- 看总览:右上角会显示「Raw Size」和「Download Size」,先心里有个数
- 点开 res/ 目录:按大小排序,看看哪些图片或资源文件最大
- 检查 lib/ 目录:有没有不必要的 .so 文件?比如只用了 armeabi-v7a,却打包了 arm64-v8a 和 x86
- 分析 DEX:点击 classes.dex,查看「Referenced Methods」和「Referenced Fields」数量
我的小技巧:在 APK Analyzer 里选中一个文件,按 Ctrl+C 可以复制它的路径。配合「Compare with…」功能,可以对比两个版本的 APK,快速看出哪里变大了。
减少 APK 体积的实战方法
我曾经接手过一个项目,APK 体积 72MB,用户反馈安装包太大。我用 APK Analyzer 一查,发现 res/ 目录占了 38MB,其中大量 PNG 图片没有压缩。下面是我总结的几条「瘦身」经验:
1. 图片资源优化
- 使用 WebP 格式:相比 PNG,WebP 能减少 25% - 35% 的体积。Android Studio 自带转换工具,右键图片 → Convert to WebP
- 开启资源混淆:在 build.gradle 中设置
shrinkResources true,配合minifyEnabled true,可以移除未使用的资源 - 使用矢量图:对于图标、简单图形,用 VectorDrawable 替代 PNG。一个 SVG 转成的 VectorDrawable 可能只有 1KB,而 PNG 动辄 10KB+
2. DEX 文件瘦身
- 开启代码混淆:ProGuard 或 R8 可以缩短类名、方法名,移除无用代码。我见过一个项目开启 R8 后 DEX 体积减少了 40%
- 避免方法数超限:如果方法数超过 65536,会生成多个 DEX 文件。检查依赖库,移除不必要的库
3. Native 库精简
- 按需打包 ABI:在 build.gradle 中配置
ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' },只保留你需要的架构 - 使用 Android App Bundle:Google Play 会根据用户设备架构只分发对应的 .so 文件,能省下不少体积
4. 资源文件清理
- 删除未使用的资源:Android Studio 的 Refactor → Remove Unused Resources 可以帮你扫描
- 复用资源:比如不同分辨率的图片,如果差异不大,可以只保留一套,用
scaleType适配
避坑指南:我曾经在开启 shrinkResources 后,发现某个动态引用的图片被误删了。原因是资源通过 getIdentifier() 方式引用,混淆工具无法识别。解决方案是在 res/raw/keep.xml 中手动声明保留。
APK 分析知识体系
下面这张图帮你理清 APK 分析的完整流程:
实战:一个完整的分析流程
假设你刚打完一个 Release APK,想看看能不能再瘦一点。我会这么做:
- 打开 APK Analyzer,拖入 APK 文件
- 查看总大小:比如 Raw Size 是 28MB,Download Size 是 22MB
- 展开 res/ 目录:发现 drawable-xxhdpi 里有一张 2.3MB 的启动图,格式是 PNG
- 右键 → Convert to WebP:选择「Lossy」质量 90%,体积降到 680KB
- 检查 lib/ 目录:发现同时有 armeabi-v7a 和 arm64-v8a 的 .so 文件,但项目只用了前者。在 build.gradle 中加上
abiFilters 'armeabi-v7a' - 开启 R8 混淆:在 release 构建类型中设置
minifyEnabled true和proguardFiles - 重新打包,再次用 APK Analyzer 分析:Raw Size 降到 18MB,Download Size 降到 14MB
一个小提醒:每次优化后,记得用 APK Analyzer 的「Compare with…」功能对比前后差异。我曾经优化完发现某个资源文件反而变大了,一查是 WebP 转换时选了无损模式,图片尺寸还变大了。换成有损 90% 质量后,肉眼几乎看不出区别,体积却小了一半。
APK 分析这件事,说白了就是「知己知彼」。你只有知道 APK 里装了些什么,才能精准地砍掉冗余。APK Analyzer 就是你的手术刀,用好了,安装包瘦个 30% 到 50% 完全不是问题。
公众号:蓝海资料掘金营,微信deep3321