前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「玲珑宝塔」优化 Apk 包大小

「玲珑宝塔」优化 Apk 包大小

作者头像
贺biubiu
发布2019-11-18 22:55:02
8020
发布2019-11-18 22:55:02
举报
文章被收录于专栏:HLQ_StruggleHLQ_Struggle

絮絮叨

工作不长不短,之前未曾考虑过深处,只是停留写出来了,便是完美。

而今的处境,不尴不尬,岁月刚好,背起行囊,继续前行。

如今的 5 G 也在万众瞩目瞩目下翩翩起舞,而 Android 近些年也惹得不少争议,所谓的谣言,不过尔尔。

每个人的追求不一样,尽自己最大努力吧。

如何减少 Apk 大小,一直以来都是处于观望状态,懒得折腾,其实还是不会,Low 的一批。

Today,一起来搞一波~

欢迎各位指正~

现学现卖~

一脑图,览无余

玲珑宝塔镇万物

首先附上一张现在 Apk 大小图:

未做任何处理原包大小为 10 MB,加固之后将近 11 MB。

以此为例,一起看看经过我们玲珑宝塔升级完,最终还剩下多少精华?

一层镇妖魔(减少 4.1 MB)

来到第一层,我们先来简单分析下是什么造成 Apk 包如此“庞大”?

上图可看到 lib 下兼容了全面的 CPU 架构,试想一下,假设未来的未来多了短视频、直播、地图导航等等(不接受杠精),这块的大小会不会成倍数的增长。

上图可看到默认支持了 89 种语言类型,目前的应用暂时未国际化,这块也可直接设置兼容中文即可,原谅我这个强迫症。

占比排行榜依次为:源代码、资源文件、lib。

我们先挑个软柿子玩玩。

1.1 设置支持语言(减少 0.2 MB)

关于这块,个人觉得虽然占比较小,但是用啥玩啥,用不到的直接干掉。

在 build.gradle 中设置仅支持中文:

代码语言:javascript
复制
defaultConfig {  ...  // 仅支持 中文  resConfigs "zh"}

这块主要是根据现有项目需求来定,中心思想只有一个,兼容哪儿个就设置哪儿个国家语言,其他的直接忽略。

设置完之后打个包,看下有没有什么变化。

从上图中可以很清晰的看到,经过设置仅支持的国家语言后,包大小减少了 0.2 MB。随后我们看下资源映射文件中关于 string 中会有什么变化。

默认语言中设置为中文,且应用也只支持了中文,少了好多东西,爽得很~

1.2 设置支持的 CPU 架构类型(减少 1.5 MB)

话说这里的 lib 为何兼容了这么多的 CPU 架构类型???

正好走到这里,关于这块的小知识再次重温下,瞅瞅 Google 为我们提供的解释:

不同的 Android 手机使用不同的 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口,即 ABI。ABI 可以非常精确地定义应用的机器代码在运行时如何与系统交互。您必须为应用要使用的每个 CPU 架构指定 ABI。

貌似 Google 商店现在支持对应的架构模式分发对应的 Apk 包,这点爽的每个包只需要兼容一种就好了。But,ummm。

目前而言,项目中使用到真正用到 So 库没几个,全部兼容太过于浪费,据说 arm 属于通用,那么这里同语言设置一样,仅支持 arm 即可。

代码语言:javascript
复制
defaultConfig {    ...    ndk {        // 设置支持的SO库架构        abiFilters "armeabi"    }}

打包运行后,继续查看现在包大小:

这块一直属于个心病,之前的项目光是 So 库就占了很大一部分空间,很湿蛋疼。

1.3 开启压缩、混淆(减少 2.4 MB)

根据 Google 官网解释,当我们使用 Android Gradle 3.4.0 或者更高版本时,默认会启用 R8 编译器进行压缩、混淆以及优化,主要项以及作用如下:

  • 代码优化:通过检测并安全移除未使用的类、字段、方法和属性;
  • 资源压缩:从应用中移除未使用的资源,此过程包含移除库依赖项中未使用的资源文件。此项常常和代码压缩配合使用;
  • 混淆:缩短类和成员的名称,从而减小 Dex 文件大小;
  • 优化:检查并重写代码,进一步减小 Dex 文件大小。例如,如果 R8 检测到从未采用过给定 if/else 语句的 else {} 分支,R8 便会移除 else {} 分支的代码。

这里需要注意一下:

默认情况下并不启用压缩、混淆和代码优化功能。因为开启后会造成 Debug 模式下编译时间较久。

关于混淆文件,这里需要正好学习一下。

混淆的意义在于什么?(引入官方解释)

混淆处理的目的是通过缩短应用的类、方法和字段的名称来减小应用的大小

混淆效果(摘自官方):

代码语言:javascript
复制
androidx.appcompat.app.ActionBarDrawerToggle$DelegateProvider -> a.a.a.b:    androidx.appcompat.app.AlertController -> androidx.appcompat.app.AlertController:        android.content.Context mContext -> a        int mListItemLayout -> O        int mViewSpacingRight -> l        android.widget.Button mButtonNeutral -> w        int mMultiChoiceItemLayout -> M        boolean mShowTitle -> P        int mViewSpacingLeft -> j        int mButtonPanelSideLayout -> K

混淆需注意:

  • Android 四大组件不能混淆;
  • 反射、注解、枚举不能混淆;
  • JS、Native 调用的方法不能混淆;
  • 基础 Bean 类以及序列化实体类不能混淆;
  • 自定义控件不能混淆;
  • 资源文件不能混淆(当然也有骚操作);

随后列举常用混淆规则(语法):

  • 保留某个类

-keep public class com.hlq.Love

  • 保留某包下的所有类及其内部类

-keep class com.hlq.** {*;}

  • 不显示指定类警告

dontwarn com.hlq.**

具体规则可文末查看官方手册。

接下来跟着官网一起实践一波~

代码语言:javascript
复制
buildTypes {    release {        // 打开资源压缩        shrinkResources true        // 开启混淆操作        minifyEnabled true         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        signingConfig signingConfigs.config    }    debug {        // 关闭资源压缩以及混淆操作        shrinkResources false        minifyEnabled false        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        signingConfig signingConfigs.config    }}

这里需要注意,在 Debug 模式下需要关闭资源压缩以及混淆操作,否则会增加编译时间,一般在发布正式包时打开即可。

混淆文件点击原文查看吧。

随后我们继续打包,查看混淆、资源压缩后 Apk 大小以及部分变化:

dex 从 3 个降低到 2 个。未 Keep 的文件均已混淆,而 Keep 的文件依旧傲娇挺立,如下图:

混淆操作,在一定程度增大了破解的难度。当然,也没有绝对的安全。

R8 每次运行时都会创建一个 mapping.txt 文件,其中列出了混淆过的类、方法和字段名称与原始名称的映射关系。此映射文件还包含用于将行号映射回原始源文件行号的信息。R8 将此文件保存在 /build/outputs/mapping// 目录中。

线上版本肯定要进行混淆,那么针对线上版本报出的异常,我们又该如何处理呢?毕竟关键内容都变成无意义字符,鉴名其意不存在了。

iTerm 2 打开:

点击 ReTrace:

这块步骤如下:

  • 导入 Mapping 文件
  • 将混淆后错误日志拷贝黏贴到 Obfuscated stack trace 中
  • 点击右下角的 ReTrace!

1.4 开启 Zipalign 优化

这块我看的很湿懵逼,估计唯有鸡大行云流水了。简单摘自官方解释:

zipalign 是一种归档对齐工具,可对 Android 应用文件进行重要的优化。其目的是要确保所有未压缩数据的开头均相对于文件开头部分执行特定的对齐。具体来说,它会使 APK 中的所有未压缩数据(例如图片或原始文件)在 4 字节边界上对齐。这样一来,即可使用 mmap() 直接访问所有部分,即使其中包含具有对齐限制的二进制数据也没关系。这样做的好处是可以减少运行应用时消耗的 RAM 容量。

如何使用?很是 easy~

代码语言:javascript
复制
buildTypes {    release {        // 开启Zipalign 优化        zipAlignEnabled true    }    debug {        zipAlignEnabled false    }}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 贺biubiu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档