乐于分享
好东西不私藏

Android APP 包体积优化

Android APP 包体积优化

Android APP 包体积优化是一个系统性工程,直接影响下载转化率用户留存更新频率。据统计,安装包每增加 10MB,下载转化率可能下降 1%~2%。

优化工作通常遵循 “分析 -> 拆解 -> 专项优化 -> 监控” 的闭环流程。以下是全方位的实战指南:


一、第一步:分析与拆解 (Analyze)

在动手前,必须清楚“大”在哪里。盲目优化往往事倍功半。

  1. 1. Android Studio APK Analyzer
    • • 操作Build -> Analyze APK... 选择你的 .apk 文件。
    • • 作用:直观展示 classes.dexresources.arsclib/res/assets/ 的占比。可以对比两个 APK 的差异,精准定位新增的大文件。
  2. 2. Bundletool (针对 AAB)
    • • 如果使用 Android App Bundle (.aab),使用 bundletool 模拟生成针对不同设备的 Split APKs,查看实际下发给用户的包大小。
  3. 3. Gradle 依赖树
    • • 命令:./gradlew app:dependencies
    • • 作用:检查是否有重复引入、版本冲突或引入了巨大的全量库。

二、核心优化维度与实战方案

1. 资源文件优化 (通常占比 40%-60%,收益最大)

资源是体积膨胀的“重灾区”,尤其是图片和字体。

  • • 图片格式转换 (关键)
    • • WebP: 将 PNG/JPG 转换为 WebP 格式。WebP 在同等质量下比 PNG 小 30%-50%,比 JPG 小 25%,且支持透明通道。Android 4.0+ 原生支持。
    • • AVIF: 如果目标 SDK 较高 (Android 12+),可尝试 AVIF,压缩率更高。
    • • 工具: Android Studio 右键图片 -> Convert to WebP;或使用命令行工具 cwebp
  • • 矢量图替代
    • • 对于图标、简单图形、Logo,优先使用 VectorDrawable (XML)
    • • 优势: 体积极小(几 KB),无限缩放不失真,可动态修改颜色。
    • • 注意: 过于复杂的矢量图(节点过多)会消耗 CPU 渲染性能,此时仍需用位图。
  • • 去除无用资源
    • • 开启 shrinkResources true (需配合代码混淆),R8 会自动移除代码中未引用的资源。
    • • 手动检查 res/rawassets 目录,删除旧的测试文件、未使用的音频/视频。
  • • 同源复用
    • • 检查是否有不同命名但内容完全相同的图片,统一复用。

2. 代码优化 (Code Shrinking)

  • • 开启 R8 / ProGuard
    buildTypes {
        release {
            minifyEnabled true// 开启代码混淆和收缩
            shrinkResources true// 开启资源收缩 (必须配合 minifyEnabled)
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    • • 作用:
      1. 1. Tree Shaking: 移除未使用的类、方法、字段。
      2. 2. 重命名: 将类名、方法名混淆为短名称 (如 a.b.c),大幅减小 Dex 体积。
      3. 3. 优化: 内联方法、移除冗余指令。
    • • 在 build.gradle 的 release 构建类型中配置:
  • • 移除冗余库
    • • 检测重复: 避免同时引入功能相似的库(如 Gson + FastJson + Jackson,或 Glide + Picasso)。
    • • 按需引入: 不要引入巨型库的全量包。例如,只需要 Google Guava 的集合功能,就只引入 guava-collections (如果拆分了) 或寻找更轻量的替代库 (如 Apache Commons Lang 的特定模块)。
    • • 移除 Debug 库: 确保 LeakCanary、Stetho 等调试库只在 debug 包中引入 (implementation vs debugImplementation)。

3. SO 库优化 (Native Libraries)

lib/ 目录通常包含不同 CPU 架构的 .so 文件,是体积第二大的部分。

  • • 只保留主流架构 (立竿见影)
    android {
        defaultConfig {
            ndk {
                abiFilters "arm64-v8a""armeabi-v7a"
            }
        }
    }
    • • 收益: 直接减少 50%-75% 的 SO 体积。
    • • 目前 Android 市场 arm64-v8a (64位) 和 armeabi-v7a (32位) 覆盖率超过 99%。
    • • 操作: 在 defaultConfig 中明确指定支持的 ABI,过滤掉 x86x86_64mips 等架构(除非你需要发布到模拟器或极少数特殊设备)。
  • • SO 合并与去重
    • • 检查多个模块是否依赖了相同版本的 SO 库,确保 Gradle 打包时进行了去重。
  • • 编译优化
    • • 如果是自研 C++ 库,使用 -Os (optimize for size) 标志编译,而非 -O2 或 -O3

4. 构建配置与分发策略 (架构级优化)

  • • 使用 AAB (Android App Bundle) - 强烈推荐
    • • 机制: 上传 .aab 到 Google Play,Google 会根据用户的设备配置(语言、屏幕密度、CPU 架构)动态生成并下发 Split APKs
    • • 收益: 用户只下载自己需要的部分(例如高分屏手机不会下载 ldpi 资源,64 位手机不会下载 x86 库)。通常可减少 20%-50% 的下载体积。
    • • 国内环境: 虽然国内商店主要认 APK,但部分商店也开始支持类似机制,或者你可以手动打多渠道分包(针对不同 ABI 或密度打不同的 APK)。
  • • 限制资源密度 (resConfigs)
    android {
        defaultConfig {
            resConfigs "zh""en""xxhdpi""xhdpi"// 只保留中英文和两种主要密度
        }
    }
    • • 如果设计稿只有一套(如 xxhdpi),可以在 defaultConfig 中强制只打包该密度资源,去掉其他密度的备用图。
  • • 限制语言资源
    resConfigs "zh""en"
    • • 同理,如果只支持中英文,排除其他几十种语言的字符串资源。

5. 动态化与云端化

  • • 动态特性模块 (Dynamic Feature Modules)
    • • 将非核心功能(如直播、AR、大型游戏模块、特定活动页)拆分为独立的 Module。
    • • 用户安装时只下载主包,需要用到该功能时再按需下载(Play Feature Delivery)。
  • • 资源云端化
    • • 非必要的启动资源(如引导页视频、大型背景图、离线字典)尽量放在 CDN,首次启动或按需下载,不打入包内。
    • • 运营活动页尽量使用 H5 或小程序容器动态加载。

三、进阶黑科技

  1. 1. ReDex (Facebook 开源)
    • • 针对 Dex 文件的字节码优化工具。它可以进行更深度的内联、去虚、常量折叠,进一步减小 Dex 体积并提升运行速度。
  2. 2. 资源混淆 (Resource Obfuscation)
    • • R8 会自动将资源文件名(如 icon_home_normal.png)混淆为短名(如 a.png),减小 resources.arsc 表的大小。确保 shrinkResources 已开启。
  3. 3. Kotlin 标准库优化
    • • 如果使用 Kotlin,确保开启了 kotlin-stdlib-jdk8 的优化,或者在较新版本中利用内置的瘦身特性。

四、持续监控与流程规范

优化不是一次性的工作,必须融入开发流程。

  1. 1. CI/CD 集成监控
    • • 在 Jenkins/GitLab CI 流水线中加入包体积检测脚本。
    • • 阈值报警: 如果新提交的代码导致包体积增长超过设定阈值(如 50KB),直接阻断构建或发送警告通知给开发者。
  2. 2. 资源审核制度
    • • 设计稿交付时,强制要求提供 WebP/SVG 格式。
    • • 禁止直接拖入未经压缩的原图(如 Photoshop 导出的超大 PNG)。
  3. 3. 定期“大扫除”
    • • 每个大版本迭代前,运行 Lint 检查和资源清理工具,移除僵尸代码和资源。

五、总结 Checklist

优化项
具体措施
预期收益
难度
图片
WebP 转换、矢量图替代、Tinypng 压缩
⭐⭐⭐⭐⭐ (极大)
SO 库
仅保留 arm64-v8a / armeabi-v7a
⭐⭐⭐⭐ (大)
代码
开启 R8 (minify & shrink)
⭐⭐⭐⭐ (大)
分发
使用 AAB (Google Play) 或 动态特性模块
⭐⭐⭐⭐ (极大,按设备)
资源
限制 resConfigs (密度/语言)、移除无用资源
⭐⭐⭐ (中)
库依赖
移除重复库、替换轻量库、按需引入
⭐⭐⭐ (中)
非核心资源
移至 CDN 动态下载
⭐⭐ (灵活)

核心心法“能矢量的不位图,能动态的不静态,能按需的不全量,能压缩的不裸奔。”