Android apk瘦身最佳实践(二):代码混淆和资源压缩

要尽可能减小 APK 文件,我们应该启用压缩来移除发布构建中未使用的代码和资源。

1. 使用 ProGuard 混淆代码

在 Android 中代码混淆和压缩都是通过 ProGuard 来实现的,ProGuard 会检测和移除代码中未使用的类、字段、方法和属性,除此外还可以优化字节码,移除未使用的代码指令,以及用短名称混淆类、字段和方法。

在 build.gradle 中,使用 minifyEnabled 属性来开启代码混淆:

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
    ...
}

2. 使用 shrinkResources 压缩资源

在 build.gradle 中使用 shrinkResources 属性来开启资源压缩,它在构建 apk 时可以移除那些没有引用到的资源文件,通常它必须与 minifyEnabled 属性一起使用:

release {
    shrinkResources true
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'),
            'proguard-rules.pro'
}

需要注意的是,开启该属性设置后,它并不会移除 values/ 文件夹中定义的资源,例如:字符串、颜色、样式等等。

3. 混淆压缩对比

为了鉴定一下代码混淆与资源压缩到底有多大作用,我们随便找个简单的 app 工程来实验一下。

minifyEnabled shrinkResources apk大小
false false 4,285,579 字节,约4.3M
true false 3,781,347 字节,约3.8M
true true 3,779,525 字节,约3.8M
false true 无法编译

从中我们可以得到一些结论:

  1. 开启代码混淆和资源压缩后,apk 大小减少了约0.5M,一个小工程都尚且如此,在一个比较庞大的工程中开启这俩选项,压缩的大小还是很可观的。
  2. 开启资源压缩与不开启相比,只减少了约2000多字节的大小,可见大头还是靠代码混淆,资源压缩只能起到锦上添花的作用。
  3. 关闭代码混淆开启资源压缩,你会发现无法编译,Android Studio 会提示你这俩必须配对使用,要开启资源压缩必须得开启代码混淆。

4. 资源压缩会保留文件名不保留内容

我们再做个测试,在应用的资源中放一张png图片姑且命名为 test.png,放一个layout布局文件命名为test.xml,并且确保这2个资源文件没有任何代码会引用,我们开启代码混淆和资源压缩打包生成apk文件。

生成apk文件后,直接将apk包拖到 Android Studio 中,可以查看apk包的相关信息,细心一点的话你会发现几个有趣的现象:

  1. 在图片资源文件夹中,仍然可以看到名为 test.png 的图片,但是你打开看到的是一个 1*1 的图片;
  2. 在 layout 文件夹中,仍然可以看到名为 test.xml 的文件,打开看到的是一个空的xml文件,没有任何xml节点信息;

也就是说,资源压缩后,并不是直接删除了没有用到的资源文件,而是生成了对应的占位文件,这些占位文件都是空文件,相比原文件大小可以忽略不计。这样做的原因是:每个资源文件都对应 R.class 里的一个资源 id ,资源 id 的映射关系会打包在 resources.arsc 文件里,如果直接删除了资源文件,则可能需要同时修改 resources.arsc 里的资源映射表,这样是很繁琐的过程,而用占位文件来替换则避免了这种情况。

5. 使用 resConfigs 去除多余的语言包

目前很多第三方库内包含了各种语言包,但是大多数情况下我们的应用是不需要国际化,仅仅需要中文的就可以了,所以可以 resConfigs 配置来去掉多余的语言包:

android {
    defaultConfig {
        ...
        resConfigs "zh"
    }
}

如上所示,打包时只会将中文的资源包打进去,这样也可以一定程度上减小 apk 的体积。

6. ProGuard 中的压缩优化配置

关于 ProGuard 的配置有很多,具体需要查看文档才能知道作用是什么。刚开始接触的时候,我以为 ProGuard 只是做代码混淆而用的,其实它的作用不仅仅如此,有2个配置我们经常会忽略掉:

  • -dontshrink
    声明不进行压缩操作。
  • -dontoptimize
    不对 class 进行优化,默认是开启优化的。由于优化会进行类合并、内联等,使用热修复的应用,建议关闭优化。

我发现很多第三方库,例如友盟统计SDK,官方给出的 ProGuard 配置都需要加上该配置,也就是说不进行代码优化、压缩,往往初次接触者不明所以的照搬了。但其实如果你的应用没有采用热更新方案之类的,在 ProGuard 里去掉这2个配置,你会发现这对减小 apk 的大小效果很显著。

以我们自己的一个应用为例,ProGuard 里加上这2个配置打出来的 apk 包大小约为 25.5M,去掉这2个配置之后打出的包大小约为 24.1M。简直不敢相信,就这么2个小小的配置,居然能让包大小缩减 1.4M 左右,效果非常明显。

但是,实操过程中,我们发现有些页面的图标丢失变成黑色了,这些因为 ProGuard 判定某些资源文件没有被使用,将它转换成了一个 1*1 的占位文件了。这需要我们手动在 res/raw/keep.xml 里配置,明确告诉 ProGuard 哪些资源文件是不需要混淆压缩的,以为自己的一个配置为例:

<?xml version="1.0" encoding="utf-8"?>
<resources
    xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="safe"
    tools:keep="@mipmap/emoji_*,@mipmap/jietiao_ic_module_*"
    >
</resources>

7. 小结

采用 ProGuard 是减小 apk 大小非常有效的方法之一,但是使用过程中可能附带很多问题:有可能打包不成功、有可能图片资源问题丢失、有可能莫明其妙的闪退,这些都需要我们对 ProGuard 的配置有个基本的了解,遇到问题才能迎刃而解,用好了它相信会有很大的帮助。

系列文章
Android apk瘦身最佳实践(一):去除R.class
Android apk瘦身最佳实践(二):代码混淆和资源压缩
Android apk瘦身最佳实践(三):资源混淆原理
Android apk瘦身最佳实践(四):采用AndResGuard进行资源混淆
Android apk瘦身最佳实践(五):图片压缩
Android apk瘦身最佳实践(六):采用D8编译器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358