APK 结构解析:从拆包看本质
做包体瘦身,第一步不是找工具,而是——你得知道 APK 里到底装了些什么。
我把 APK 后缀改成 .zip,直接解压,就能看到它的内脏。嗯,我第一次这么做的时候还挺惊讶的:原来 Android 安装包就是个压缩包而已。
APK 的核心构成
解压后,你会看到这么几样东西:
- AndroidManifest.xml —— 配置清单,声明权限、组件、版本
- classes.dex(可能多个)—— Dalvik 字节码,你的 Java / Kotlin 代码编译后的产物
- resources.arsc —— 编译后的资源索引表,包含字符串、颜色、布局 ID 等
- res/ —— 布局、图片、drawable、mipmap 等资源
- lib/ —— native 库,.so 文件(armeabi-v7a、arm64-v8a、x86 等)
- assets/ —— 原生资源文件(通常放字体、配置文件、模型等)
- META-INF/ —— 签名文件、清单摘要
除此之外,可能还有 kotlin/(Kotlin 标准库反射文件)、com/(额外的类文件,极少见)。
各模块体积占比(典型项目)
我统计过几个中型项目,做个参考:
| 模块 | 典型体积占比 | 说明 |
|---|---|---|
| classes.dex | 30% ~ 50% | 代码最重,方法数越多体积越大 |
| resources.arsc | 5% ~ 15% | 资源索引,国际化字符串多会暴增 |
| res/ | 20% ~ 40% | 图片资源是主力,尤其是 mipmap |
| lib/ | 10% ~ 30% | 带多个 CPU 架构会爆炸 |
| assets/ | 5% ~ 20% | 大文件重灾区(字体、视频、模型) |
| META-INF | < 1% | 基本可以忽略 |
看到没?classes.dex、res、lib 这三个占了 80% 以上。瘦身就盯着它们打。
怎么快速查看 APK 结构?
不用 IDE,两条命令搞定:
# 1. 用 unzip 解压看目录
unzip -l your-app.apk | sort -k4 | more
# 2. 用 aapt(Android SDK 自带)查看关键信息
aapt dump badging your-app.apk
aapt list your-app.apk
我个人推荐 aapt:它不仅能列文件,还能告诉你每个资源 ID、版本号、最低 SDK 版本、权限用量。有一次我发现一个 APK 的 minSdkVersion 设成了 14,导致兼容包体积巨大——这种坑,光看 unzip 是不容易发现的。
深入解析每个文件夹
1. classes.dex —— 代码最集中的地方
Android 会把所有 Java/Kotlin 类编译成一个(或多个)DEX 文件。如果方法数超过 65536,就会产生多个 classes2.dex、classes3.dex……
避坑提醒:我曾经接手过一个项目,主 DEX 里塞满了 unused 的第三方库(比如 Retrofit、OkHttp、Gson 全套),但实际只用到了一个请求。结果 DEX 体积直接超过 10MB。解决办法很简单——移除无用依赖,或者用 R8 精简掉未调用的方法。
2. resources.arsc —— 资源索引表
这个文件里存放的是资源 ID 与资源路径的映射关系,以及所有字符串常量。如果你的 App 支持 30 种语言,每次添加 string 都会膨胀这个文件。
我记得有一次,产品要求支持 40 种语言,翻译团队给了每语言一个 strings.xml 文件,结果 resources.arsc 直接翻了 3 倍。后来我建议只保留主流 5 种语言,其余用 fallback,体积立刻降下来。
3. res/ 下的图片
这里藏着 大多数字节。尤其是 mipmap 目录里的启动图标、高分辨率背景图,很多设计师喜欢直接扔 1920x1920 的 PNG,一个图标就能吃掉几百 KB。
核心原则:
- 用 WebP 替代 PNG,压缩率提升 25%~40%
- 只保留需要的分辨率(ldpi、mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi),清理不需要的
- 矢量图(VectorDrawable)替代位图——适用于图标和简单图形
4. lib/ —— native 库的烦恼
Android 支持多种 CPU 架构:armeabi-v7a、arm64-v8a、x86、x86_64。如果你在 APK 里塞了所有架构的 .so,体积立刻翻倍。
我曾经踩过坑:第三方 SDK 提供了 4 个架构的 so,我全扔进去了,APK 从 15MB 变成 28MB。后来改成只保留 arm64-v8a(主流),x86 版本单独发包,体积回到 18MB。
5. META-INF
签名信息、证书、清单。一般不会超过 100KB,不用操心。
APK 结构全景图
下面这张图帮你梳理了整个 APK 的骨架。红色圈出的部分是瘦身主战场。
瘦身之前,先用 unzip 或 aapt 彻底了解你的 APK 结构。
重点关注:DEX 方法数 & 无用代码 → resources.arsc 的国际化内容 → res 目录的图片 → lib 的多架构 so。
这四大块啃下来,包体体积至少降 30%。
实战小贴士:我常用的检查命令
除了解压,我还会用这个脚本来分析各文件夹大小:
#!/bin/bash
# 安装 xmlstarlet 或使用 python 解析
# 快速统计 APK 内各种资源占比
apkfile='your-app.apk'
unzip -l $apkfile | awk '{print $4, $1}' | sort -k2 -rn | head -20
这么一跑,哪个文件是「体积胖子」一目了然。我个人习惯在持续集成(CI)中加入这个脚本,每次构建后自动输出 APK 内各模块的大小报表。这样团队里一旦有人不小心引进了大资源库,立刻能发现。
总结
APK 结构并不复杂。你把它当成一个大箱子,里面装着代码、资源、库。知道每个格子的重量,就知道从哪里下刀。