Android Apk 大小分析 (一)精简版
最近在做一个项目,由于 app 是运行与小型 Android 设备上,对 apk 的启动速度和 apk 大小有一定需求,要求 apk 越精简越好,也就是越小越好。
但是我一开始,并没有注意这个问题,引入了很多的库,等项目开发完毕后,发现 debug apk 有 19MB 多,Release 版本有 15MB 多。此时并没有开启Minify这显然是不符合条件的。但是,开启了 Minify后出现很多的报错,怎么解决都解决不完,索性就直接重新新建项目来研究一下 apk 的大小问题。
场景一:只有一个基础 Activity 的 apk 有多大?
我打算采用两种方式来进行测试,一种是 kotlin 语言,一种是 java 语言。首先我们使用 kotlin。
需要注意的是,我们的app 的 gradle 中没有引入任何库,并且在 gradle 中开启了 minifyEnable 和 shrinkResources。gradle中关键信息如下:


1. Kotlin方式
1.1 基础 Activity 版本 apk
首先,我们使用 kotlin 语言进行一次测试,我们编写一个简单的界面然后,编译出 Release 版本的 apk,分析一下其大小。

采用原生 Activity,没有导入和使用任何第三方库的情况下,采用 kotlin 语言,我们运行./gradlew assembleRelease 看看编译出的 apk 有多大。
答案是 60KB 左右。

那么我们用ide 打开 apk 看一下里边的内容如下:

我们可以看到,60KB里边的大部分是res 目录,也就是应用的 logo,kotlin 引入的文件夹和相关文件大约占用了 10.5KB,而 classes.dex 只占用了 524 Byte,amazing!!
那么我们来看看 dex文件中有哪些内容:

我们可以看到,只有最基础的一个 Activity 界面,以及对 Activity 的三个方法的引用。占用空间非常小。
1.2 去掉多余 logo
我把所有 logo 都删掉,只保留一个 8kb 的高清 logo,放到 drawable 文件夹中,然后修改 manifest

然后我们再次打包 Release apk,效果如下:

Boom!!!!!! apk 尺寸降低到了 25KB!!! Amazing !!!!

打开 apk,我们可以看到,删掉logo 文件后显著减少了 res容量。那么我们来横向对比一下 纯Java 方式打包的 apk 有多大。
2. Java
2.1 基础 Activity 版本 apk
只有 Activity ,全量 logo 情况下,答案是 47KB,那么我们看看内部组成:

我们可以看到,首先,他没有 10.5KB 左右的 kotlin 文件夹,res 目录和 kotlin 是一样的, 所以总体相比 kotlin 版本减少了11KB 左右,由此我们可出结论,kotlin 版本 apk 至少会增加 11KB 左右的 Kotlin 标准库的内置信息和元数据文件 文件夹。
2.2 去掉多余的 logo
那么同理如果我们把 logo 去掉呢,最小的 Java 版本 apk 是多少呢?答案是:8KB,内容如下:

场景二:引入androidx.appcompat库,并将 Activity 替换为 AppCompatActivity
我们在场景一的基础上,引入androidx.appcompat,并且只将 Activity 替换为 AppCompatActivity, 此时编译出来的 apk 有多大呢?不管是 Kotlin 还是 Java, apk 的大小都达到了 680 KB左右,也就是说,androidx.appcompat直接引入了 670KB 左右的内容大小。我们打开 apk 看一下:
-
Kotlin 版本:
![image]()
-
Java 版本:
![image]()
java 版本这里有意思的一点是,引入后,他的 apk 中也出现了 kotlin 的文件夹,我猜测是androidx.appcompat是kotlin 编写的,所以,引入他也导致了引入了 kotlin 依赖。
也就是说我们在上一章节中抠抠搜搜去掉的二三十 KB 的空间,在引入了一个三方库后,显得十分可笑。不过这里需要知道的是 appcompat 是一个非常大的库。以下是 Gemini 解释的 androidx.appcompat:appcompat 的作用。
您引用的这个依赖:
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
指的是 androidx.appcompat:appcompat 库,它是 Android Jetpack 库中 最核心、最重要的库之一。
1. appcompat 包的作用是什么?
appcompat 的核心作用是提供 向后兼容性 和 现代 UI 功能,允许您的应用在旧版本的 Android 设备上使用最新的功能和设计标准(特别是 Material Design)。
具体来说,它提供了以下关键功能:
- 向后兼容性 (Backwards Compatibility)
- 允许您在旧版本的 Android 系统上(通常一直兼容到 API 级别 21,甚至更低)使用新版 API 中引入的许多功能和类。
- 例如,它提供了
AppCompatActivity、AppCompatButton、AppCompatTextView等,这些类在底层处理了不同 Android 版本之间的差异。
- 核心 UI 组件
- 提供了核心的 UI 基础结构,例如:
ActionBar或Toolbar:允许在所有支持的 API 级别上使用操作栏或工具栏。- Material Design 风格:即使在旧设备上,也能通过使用
Theme.AppCompat系列主题来获得一致的 Material Design 视觉效果。 - 资源和主题兼容:对颜色、矢量图 (Vector Drawables) 和主题属性进行向后移植,确保它们在所有设备上都能正确渲染。
- 提供了核心的 UI 基础结构,例如:
- Fragment 支持
- 它通常还会传递依赖
androidx.fragment库,为管理屏幕片段(Fragment)提供兼容的 API。
- 它通常还会传递依赖
- 夜间模式 (Night Mode) 支持
- 提供了
AppCompatDelegate来支持在各种 Android 版本上切换应用的深色/夜间主题。
- 提供了
简单来说: 只要您的应用想要在广泛的 Android 设备上运行,并且想要使用 Material Design 和现代的 Android UI 最佳实践,那么 appcompat 是几乎必不可少的。
2. 它很大吗?
在 Android 依赖库中,appcompat 库相对来说是比较大的。
- 大小估算:根据一些公开的讨论和 Issue 追踪(例如 Google Issue Tracker),如果一个项目只添加了
appcompat库(且没有开启代码混淆/收缩),可能会导致 APK 大小增加约 700 KB 到 800 KB 甚至更多。 - 原因:它体积大的原因是它不是一个简单的工具类库,而是包含了大量的 兼容性代码、资源文件(如各种版本的颜色、主题、矢量图等),以及一套完整的 UI 框架,以便在旧设备上模拟新版系统的行为。
- 实际影响:
- 开启 R8/ProGuard/资源收缩后:在实际的 Release 构建中,如果您开启了 R8(代码和资源收缩),R8 会移除所有未被使用的兼容性代码和资源,因此
appcompat最终对 APK 大小的贡献会大幅减小。
- 开启 R8/ProGuard/资源收缩后:在实际的 Release 构建中,如果您开启了 R8(代码和资源收缩),R8 会移除所有未被使用的兼容性代码和资源,因此
结论:appcompat 是一个功能强大且必要的库。虽然它在原始 JAR/AAR 文件中体积较大,但在优化后的 Release APK 中,它的实际影响是可以接受的,而且它带来的兼容性和功能性价值远超其体积。



浙公网安备 33010602011771号