返回博客

加固后包体反而更大?3个让APK体积暴增的隐藏原因

你有没有过这种经历:给 APK 加固之后,用加固工具一看,包体体积反而比加固前大了十几 MB。我第一次遇到这个问题的时候,第一反应是工具出了问题,或者是中了什么恶意软件。后来仔细排查了一遍才发现,加固后包体变大这件事,其实是个挺普遍的现象,但原因很多人都不知道。

加固后包体反而更大?3个让APK体积暴增的隐藏原因

你有没有过这种经历:给 APK 加固之后,用加固工具一看,包体体积反而比加固前大了十几 MB。我第一次遇到这个问题的时候,第一反应是工具出了问题,或者是中了什么恶意软件。后来仔细排查了一遍才发现,加固后包体变大这件事,其实是个挺普遍的现象,但原因很多人都不知道。

我后来专门花时间研究了一下 APK 加固和包体大小的关系,发现问题主要出在几个地方:有的确实是无用代码没有被清理、有的是签名信息被重复打包、有的是加固后的 DEX 经过了不同的压缩处理。

今天把这个话题彻底讲清楚,帮大家避坑。

一、加固的原理和包体变化的关系

1.1 常见的加固技术方案

目前市面上常见的 APK 加固方案主要有三类:

第一类是整体加壳,把原始 APK 包裹在一个外壳里,运行的时候先启动外壳程序,再解密并加载原始 APK。这类的代表是娜迦、梆梆等传统加固厂商。整体加壳的效果好,但包体增量也最大,通常会增加 3-10 MB。

第二类是 DEX 加密,只加密核心的 DEX 文件,运行时通过 native 代码解密并加载。这种方案的包体增量较小,通常在 1-3 MB,但对加固厂商的技术要求高。

第三类是代码混淆,不加密整个 APK,只对代码进行混淆处理,增加逆向分析的难度。这类方案不会增加包体大小,甚至可能略微减小,但保护效果也最弱。

2026年的主流方案是第二类和第三类的组合,单纯加壳的方案已经越来越少人用了。

1.2 加固后包体变大的正常原因

有些包体变大属于正常现象,加固过程中确实会引入额外的代码和数据:

外壳程序:整体加壳方案需要额外的外壳程序来解密和加载原始 APK,这部分代码和数据是新增的,无法避免。

签名信息:有些加固工具会重新签名 APK,如果签名信息没有复用原始签名,增量会更大。

资源压缩:有些加固工具在加固的同时会做资源压缩,这反而会让包体变小。但如果加固后的包体变大,通常是其他原因。

二、3个让包体暴增的隐藏原因

2.1 原因一:SDK 叠加打包

这是最常见但最隐蔽的问题。很多团队在项目里引入 SDK 的时候,不注意检查是否已经有同类型的 SDK 在包里了。

举个例子:你的游戏接入了 Facebook SDK 用于登录和分享,同时又接入了 Firebase SDK 用于推送和崩溃统计。但 Firebase SDK 本身也内置了 Facebook 的部分库,导致你的 APK 里出现了两套 Facebook SDK。

当你再加固的时候,加固工具会保留所有文件,导致重复的库文件被加固后重新打包,包体就膨胀了。

排查方法:用 Android Studio 的 APK Analyzer 或者 build-tools 里的 aapt2 工具分析 APK 的内容结构:

aapt2 dump badging your-app.apk | grep "sdk"

这个命令会列出 APK 使用的所有 SDK 版本信息。如果发现同一个 SDK 有多个版本,需要在 build.gradle 里用 exclude 规则去掉重复。

正确做法:在接入多个 SDK 之前,先查一下它们之间的依赖关系。推荐使用 gradle dependencies 命令查看完整的依赖树,提前发现可能的重复依赖。

2.2 原因二:资源文件未清理

这个问题往往发生在项目维护了很久之后。团队在开发过程中添加了很多资源文件,比如调试用的图片、多语言资源、已经不用的音频文件等。这些资源在打包的时候被自动包含进 APK,但应用运行时根本用不到。

我见过一个极端案例:一个游戏项目积累了 2GB 的资源文件,但实际用在游戏里的只有 200 MB。打包的时候所有资源都被塞进 APK,导致包体达到 800 MB,加固之后更是超过了 1 GB。

排查方法:用 build-tools 里的 aapt 工具列出 APK 里包含的所有资源:

aapt list -f your-app.apk | grep -E "\.(png|jpg|mp3|wav|ogg|ttf)$"

如果发现大量你不认识的资源文件名,说明可能有无用的资源在包里。

清理工具:推荐使用 Google 官方的 Android Resource Shrinking 功能,在 build.gradle 里启用:

android {
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
        }
    }
}

这个功能会在打包的时候自动移除未使用的资源文件。

2.3 原因三:SO 库架构未过滤

这是让包体暴增最厉害的原因之一。Android 应用支持的 CPU 架构有 armeabi-v7a、arm64-v8a、x86、x86_64 四个,每个架构都有对应的 SO 库文件。

如果不做任何处理,打包的时候所有架构的 SO 库都会被包含进去。但实际上,你的应用只需要支持 1-2 个主流架构就够了,不需要覆盖所有。

数据对比:以一个包含 5 个 SO 库的应用为例:

  • 只打包 arm64-v8a:包体增量约 15 MB
  • 打包 arm64-v8a + armeabi-v7a:包体增量约 25 MB
  • 四个架构全部打包:包体增量约 40 MB

加固的时候,如果不对架构进行过滤,增量会被放大,可能导致包体增加 50 MB 以上。

正确做法:在 build.gradle 里明确指定需要支持的架构:

android {
    defaultConfig {
        ndk {
            abiFilters 'arm64-v8a'  // 只支持64位ARM架构
        }
    }
}

大多数情况下,只支持 arm64-v8a 就够了。如果你的应用需要覆盖更多设备,可以加上 armeabi-v7a,但没必要支持 x86 和 x86_64,除非你的目标用户里有大量使用 Android 模拟器的。

三、包体优化清单

3.1 加固前的准备工作

在加固之前,建议先做一次完整的包体审计:

第一步:分析 APK 结构。用 APK Analyzer 或者 aapt2 工具查看 APK 里都包含了哪些文件,记录每个部分的大小占比。

第二步:清理无用资源。运行 Android Resource Shrinking,移除未使用的资源文件。

第三步:过滤 CPU 架构。确认需要的 SO 库架构,在打包配置里明确指定。

第四步:检查重复依赖。用 gradle dependencies 查看依赖树,找出并移除重复的 SDK。

3.2 加固后的验证

加固完成之后,也要检查加固后的 APK:

大小对比:记录加固前后的包体大小变化,如果增量超过 10 MB,需要排查原因。

功能验证:确保加固后的 APK 可以正常安装和运行,所有功能不受影响。

签名验证:用 apksigner 验证签名是否正确,确保可以正常更新。

总结

加固后包体变大这件事,大多数情况下是可以在加固之前预防的。只要做好依赖管理、资源清理、架构过滤三个环节,包体增量可以控制在合理范围内。

我建议今天就检查一下你的项目:用 APK Analyzer 打开你的 APK,看看包体里最大的是哪部分、是否有重复的依赖、是否有大量未使用的资源。如果发现了问题,现在就开始优化,不要等到包体大到无法收拾了才后悔。

你的项目 APK 目前有多大?加固后增量是多少?评论区说说,我们一起看看有没有优化空间。

想把你的 APP 稳上 Google Play?

不过审不收费,最快 3 天过审

免费咨询