Android性能优化--包体积优化

原因

  1. 下载转化率

    包体积越小,用户下载等待的时间也会越短,所以下载转换成功率也就越高。同时国内应用市场使用流量下载时会有流量保护机制,如果安装包体积超过阈值,那么在下载时候便有流量安装提醒,相应的对于用户来说安装过程需要多一步操作,这也会影响用户安装的欲望。

  2. 渠道商要求

    当 App 做大之后,可能需要和手机厂商合作预装,这些渠道商也会要求安装包体积不能超过制定阈值,同时安装包体积越大,所需 CDN 流量费用越高。

  3. App 性能

    安装包体积越大,相应的安装时间、签名校验时间越长,运行时内存与ROM空间占用越大。

分析

apk构成

  • lib/

so 文件目录,可能会有armeabi、armeabi-v7a、arm64-v8a、x86、x86_64、mips。目前只需支持 armeabi-v7a、arm64-v8a 即可,后面随着应用商店64位要求落地,可删除 armeabi-v7a。

  • assets/

应用资源,不会生成资源id,可使用 AssetsManager 对象获取资源。

  • res/

应用资源,通过 aapt 生成资源id,并保存在 .R 文件和 resource.arsc 文件中。

  • META-INF/

包含 CERT.SF 和 CERT.RSA 签名文件,以及 MANIFEST.MF 清单文件。

  • .dex文件

代码编译成 .class 文件后,再经过 dex 工具编译生成一个 .dex 文件。

  • resources.arsc

包含已编译的资源。此文件包含 res/values/ 文件夹的所有配置中的 XML 内容。打包工具会提取此 XML 内容,将其编译为二进制文件形式,并将相应内容进行归档。此内容包括语言字符串和样式,以及未直接包含在 resources.arsc 文件中的内容(例如布局文件和图片)的路径。

apk打包流程

分析工具

Android Studio

直接将 apk 拖进 Android Studio 中就可以自动使用 Analyze APK 打开 apk。然后就可以看到 APK 文件的绝对大小以及各组成文件的百分占比,如下图所示:

可以看到该 apk 中占比最大的是 .dex 文件,其次是 lib,所以包体积优化的重点区域在 dex 优化。当然这是一个 demo 项目,并不具有标志性,下面看一个线上 apk:

image.png

该 apk 中占比就非常鲜明,lib 文件夹占了包体积一半以上,所以重点优化在 so 优化,其次占比较大的是 assets 和 res 两个文件夹,所以还可以对 resouces 优化。

方案

so优化

so文件缩减

根据市面上手机cpu架构分布,选择保留 armeabi-v7a 和 arm64-v8a 即可。后面各大应用商店强制要求64位后,可以考虑仅保留 arm64-v8a 即可。

android {
    defaultConfig {
        ndk {
            abiFilters 'arm64-v8a'
        }
    }
}
复制代码

SO 压缩与解压

  1. ⼲预 gradle apk 打包流程,在 gradle merge 本地库之后,打包 apk 之前使用 XZ 或 7-Zip 将SO进行压缩,生成压缩⽂件保存到assets⽬录之下。
  2. 在默认的 lib 目录,我们只需要加载少数启动过程相关的 Library,其他的 Library 我们都在首次启动时异步解压、加载(可通过 Facebook 开源框架 SoLoader)。

SO 动态下发

与 so 压缩/解压 思路一样,在应用启动后异步下载 so 文件。具体落地可参考 mp.weixin.qq.com/s/X58fK02im…

dex优化

开启 minifyEnabled、shrink、progurard

开启缩减、优化、混淆,移除无用的 class、字段和方法。

android {
    buildTypes {
        release {
            // Enables code shrinking, obfuscation, and optimization for only
            // your project's release build type.
            minifyEnabled true

            // Enables resource shrinking, which is performed by the
            // Android Gradle plugin.
            shrinkResources true

            // Includes the default ProGuard rules files that are packaged with
            // the Android Gradle plugin. To learn more, go to the section about
            // R8 configuration files.
            proguardFiles getDefaultProguardFile(
                    'proguard-android-optimize.txt'),
                    'proguard-rules.pro'
        }
    }
    ...
}
复制代码

去除 debug 信息与行号信息、Dex 分包优化

可借助 ReDex (facebook 开源黑科技) 移除 dex 中多余的 debug item 块、method id、跨dex 调用造成的冗余信息。

裁剪三方库

  • 统一基础三方库,避免同一个功能引入多个三方库,例如:为显示图片引入 Glide、Fresco 三方库。
  • 修改三方库源码,仅保留所需功能。

重复代码

使用 Simian工具 或者 Lint 来扫描出重复的代码。

source 优化

图片

  • 使用 tinypng 进行压缩。已有 IDEA 插件,可以搜索 TinyPngPlugin。在 Android 的构建流程中,AAPT 会使用内置的压缩算法来优化 res/drawable/ 目录下的 PNG 图片,但这可能会导致本来已经优化过的图片体积变大,因此,可以通过在 build.gradle 中 设置 cruncherEnabled 来禁止 AAPT 来优化 PNG 图片,代码如下所示:

    aaptOptions {
        cruncherEnabled = false
    }
    复制代码
  • 启用 webp,可以将 png 转为 webp

  • 启动 SVG,可以将元素不复杂的 icon 使用 SVG 引入。但需要注意如果 icon 中元素复杂,例如渐变等,在编译时会自动生成对应的全尺寸图片(mdpi~xxxhdpi),反而会增加包体,这种可以考虑使用 webp

  • 开启资源缩减。gradle 中配置 shrinkResource = true

资源混淆

可以接入微信团队开源的 AndResGurad,实现资源命名的混淆

语言包

可以配置仅保留中文语言

defaultConfig {
    resConfigs("en","zh","zh-rCN")
}
复制代码

资源文件

可以配置仅保留需要的资源文件

defaultConfig {
    resConfigs("xxhdpi","xxxhdpi")
} 
复制代码

移除无用的 assets

可借助 Matrix 扫描无用的 assets 资源。需要注意静态 html 等资源因为没有 dex 显示持有,会出现误删问题。

原理:

  1. 解压 apk,找到所有的 assets 资源集合 A
  2. 反解 dex,获取所有的 class 引用的 assets 集合B
  3. 取 A 与 B 的差集,即为无用 assets

拓展优化

  • 避免使用枚举。如果可能,请考虑使用 @IntDef 注释和 代码缩减 移除枚举并将它们转换为整数。此类型转换可保留枚举的各种安全优势。
  • 插件化
  • H5、小程序化
  • 删除无用或低价值业务功能

防劣化

包体积的监控,主要可以从如下 三个纬度 来进行:

  • 1)、大小监控:通常是记录当前版本与上一个或几个版本直接的变化情况,如果当前版本体积增长较大,则需要分析具体原因,看是否有优化空间
  • 2)、依赖监控:包括J ar、aar 依赖
  • 3)、规则监控:我们可以把包体积的监控抽象为无用资源、大文件、重复文件、R 文件等这些规则

包体积的 大小监控依赖监控 都很容易实现,而要实现 规则监控 却得花不少功夫,幸运的是 Matrix 中的 ApkChecker 就实现了包体积的规则监控。

资料

缩减、混淆处理和优化应用  |  Android 开发者  |  Android Developers

深入探索 Android 包体积优化(匠心制作-上) - 掘金

包体积优化 · 方法论 · 揭开包体积优化神秘面纱 - 掘金

Android修炼系列(22),我的 apk 瘦身知识点 - 掘金

包体积优化(上):如何减少安装包大小?-极客时间

分类:
Android