在配置了crunchPngs(图像压缩) true的情况下,png图片的压缩是否会减少包大小
| 操作 | 包大小 |
|---|---|
| crunchPngs false | 71.6 MB (75,105,580 字节) |
| crunchPngs true | 67.5 MB (70,803,404 字节) |
| tinypng+crunchPngs true | 66.6 MB (69,890,184 字节) |
-压缩图片信息
| 文件名 | 压缩前 | crunchPngs压缩后 | tinypng+crunchPngs压缩后 | 转webp无损压缩(未经crunchPngs) |
|---|---|---|---|---|
| bg_vip_home.png | 793 KB (812,431 字节) | 587.25K | 76.45K | 430 KB (441,232 字节) |
| gonglve_iv_1.png | 799 KB (819,116 字节) | 536.25K | 133.83K | 406 KB (416,394 字节) |
推荐一个网站png图片压缩
由上面结论可以得出,压缩png图片在配置了crunchPngs.能大大减少图片资源的体积从而减少包的大小.
同样的通过自己精简png图片的方式也可以减少包大小.
crunchPngs配置的相关信息
1. 我们在build文件中配置了此项信息后gradle会把此配置读取到dsl文件中.并在执行打包action的时候处理此项配置.
2. 通过aapt进行资源的压缩.
aapt相关介绍文档,有兴趣的可以查看研究
分析apk包
我们可以通过build->output->apk->flavor名称(这里是neibu)->双击apk包来用studio打开apk包进行分析.
混淆配置文件的产物
- dump.txt:描述apk文件中所有类的内部结构
- mapping.txt:混淆前后的类、类成员、方法的对照关系(重要,追溯Crash堆栈信息要用到)
- resources.txt:资源文件的压缩信息
- seeds.txt:未被混淆的类和成员
- usage.txt:被移除的代码
移除无用代码的方式猜想.
- 因为通过seeds.txt可以看出未被混淆的类和成员,我们可以查看此文件,确定一下此文件中所记录的类和成员是否是必须不能被混淆,能被混淆的话我们可以通过修改混淆配置文件去混淆这些文件.
- 因为通过usage.txt可以看出被移除的代码,我们可以通过追踪此文件中自己手写的代码部分,然后手动移除无用代码.
代码压缩
- 从应用及其库依赖项中检测并安全地移除未使用的类、字段、方法和属性
资源压缩
- 移除未使用资源
从封装应用中移除未使用的资源,包括应用的库依赖项中未使用的资源。此功能可与代码压缩结合使用,这样一来,移除未使用的代码后,也可以安全地移除不再引用的任何资源
要启用资源压缩,请在 build.gradle 文件中将 shrinkResources 属性设为 true
- 严格引用审查
您的代码调用了 Resources.getIdentifier()(或您的任何库进行了这一调用 - AppCompat 库会执行该调用),这就表示您的代码是根据动态生成的字符串查询资源名称。当您执行这一调用时,资源压缩器默认情况下会采取防御性行为,将所有具有匹配名称格式的资源标记为可能已使用,无法移除。
以下代码会使系统将所有带 img_ 前缀的资源标记为已使用。
val name = String.format("img_%1d", angle + 1)
val res = resources.getIdentifier(name, "drawable", packageName)
- 移除未使用的备用资源
Gradle 资源压缩器只会移除未由您的应用代码引用的资源,这意味着,它不会移除用于不同设备配置的备用资源。如有必要,您可以使用 Android Gradle 插件的 resConfigs 属性来移除您的应用不需要的备用资源文件。
例如,如果您使用的是包含语言资源的库(如 AppCompat 或 Google Play 服务),则 APK 将包含这些库中消息的所有已翻译语言字符串,无论应用的其余部分是否翻译为同一语言。如果您希望只保留应用正式支持的语言,可以使用 resConfig 属性指定这些语言。系统会移除未指定语言的所有资源。
以下代码段展示了如何将语言资源限定为仅支持英语和法语:
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
同样,您也可以通过编译多个 APK,让每个 APK 以不同的设备配置为目标,自定义要包含在 APK 中的屏幕密度或 ABI 资源。
- 合并重复资源
默认情况下,Gradle 还会合并同名的资源,如可能位于不同资源文件夹中的同名可绘制对象。这一行为不受 shrinkResources 属性控制,也无法停用,因为当多个资源与代码查询的名称匹配时,有必要利用这一行为来避免错误。
只有在两个或更多个文件具有完全相同的资源名称、类型和限定符时,才会进行资源合并。Gradle 会在重复项中选择它认为最合适的文件(根据下述优先顺序),并且只将这一个资源传递给 AAPT,以便在 APK 文件中分发。
Gradle 会在以下位置查找重复资源:
与主源集关联的主资源,通常位于 src/main/res/。 变体叠加,来自编译类型和编译特性。 库项目依赖项。 Gradle 会按以下级联优先顺序合并重复资源:
依赖项 → 主资源 → 编译特性 → 编译类型
例如,如果某个重复资源同时出现在主资源和编译特性中,Gradle 会选择编译特性中的资源。
如果完全相同的资源出现在同一源集中,Gradle 无法合并它们,并且会发出资源合并错误。如果您在 build.gradle 文件的 sourceSet 属性中定义了多个源集,则可能会发生这种情况。例如,如果 src/main/res/ 和 src/main/res2/ 包含完全相同的资源,就可能会发生这种情况。
混淆
- 缩短类和成员的名称,从而减小 DEX 文件大小。
优化
-
检查并重写代码,以进一步减小应用 DEX 文件的大小。
例1:如果 R8 检测到从未采用过给定 if/else 语句的 else {} 分支,R8 便会移除 else {} 分支的代码。 例2:如果您的代码只在一个位置调用某个方法,R8 可能会移除该方法而将其内嵌在这一个调用点。 例3:如果 R8 确定某个类只有一个唯一的子类且该类本身未实例化(例如,一个抽象基类仅由一个具体实现类使用),那么 R8 可以将这两个类组合在一起并从应用中移除一个类。
名词解释:
-
minifyEnabled=true 会启用R8代码压缩
是指移除 R8 确定在运行时不需要的代码的过程。例如,如果您的应用包含许多库依赖项,但仅利用它们的一小部分功能,那么此过程可以大大减小应用的大小。R8会自动为您生成大多数应用项目(如应用的 Activity、view和service)所需的保留规则以及ProGuard -keep作为不应舍弃的类和应用入口点.
-
shrinkResources=true 压缩资源
使资源压缩器确定应用仍然使用的资源,并移除未被使用的资源,此功能最好在设置了代码压缩的同时使用.这样就能够删除无用代码引用无用资源.
参考文献: