Android SDK开发艺术探索(六)压缩与优化

3,177 阅读3分钟

一、前言

本篇是Android SDK开发艺术探索系列的第六篇文章,简单介绍了SDK开发中关于SDK包体积优化相关的知识。包括APK与AAR组成分析、SDK包大小与集成增量的概念以及SDK开发中的资源压缩与优化思路。包体积的控制是一个极其繁琐的系统工程,有非常多的方案可以实践,关键在于投入产出比。本文未曾想罗列网文中的所有优化方案,而是希望通过介绍简单可行的配置来压缩、优化SDK。更希望这是一个思维上的启发,唤醒一颗持续优化的心,以及在SDK开发中对于压缩与优化实践的特点。认识SDK组成,探索SDK开发在包体积压缩、控制集成增量上的最佳实践。

系列文章:

Android SDK开发艺术探索(一)开篇与设计

Android SDK开发艺术探索(二)Exception or ErrorCode

Android SDK开发艺术探索(三)初始化

Android SDK开发艺术探索(四)个性化配置

Android SDK开发艺术探索(五)安全与校验

Android SDK开发艺术探索(六)压缩与优化

Android SDK开发艺术探索(七)依赖原则与打包方法

二、apk与aar组成分析

2.1、APK文件组成

APK 文件由一个 Zip 压缩文件组成,包含了构成应用的所有文件。包括 Java 类文件、资源文件和包含已编译资源的文件。

APK 包含如下目录:

  • META-INF/:包含 CERT.SFCERT.RSA 签名文件,以及 MANIFEST.MF 清单文件。
  • assets/:包含应用的资源;应用可以使用 AssetManager 对象检索这些资源。
  • res/:包含未编译到 resources.arsc 中的资源。
  • lib/:包含特定于处理器软件层的已编译代码。此目录包含每种平台类型的子目录,如 armeabiarmeabi-v7aarm64-v8ax86x86_64mips

APK 还包含以下文件。在这些文件中,只有 AndroidManifest.xml 是必需的。

  • resources.arsc:包含已编译的资源。此文件包含 res/values/ 文件夹的所有配置中的 XML 内容。打包工具会提取此 XML 内容,将其编译为二进制文件形式,并压缩内容。此内容包括语言字符串和样式,以及未直接包含在 resources.arsc 文件中的内容(例如布局文件和图片)的路径。
  • classes.dex:包含以 Dalvik/ART 虚拟机可理解的 DEX 文件格式编译的类。
  • AndroidManifest.xml:包含核心 Android 清单文件。此文件列出了应用的名称、版本、访问权限和引用的库文件。该文件使用 Android 的二进制 XML 格式。

APK文件组成概览

2.2、AAR文件组成

AAR 文件的文件扩展名为 .aar,此文件本身也是一个 zip 文件,其中必须包含以下文件/目录:

  • /AndroidManifest.xml
  • /classes.jar
  • /res/
  • /R.txt

此外,AAR 文件可能包含以下一个或多个可选文件/目录:

  • /assets/
  • /libs/name.jar
  • /jni/abi_name/name.so(其中 abi_name 是 Android 支持的ABI之一)
  • /proguard.txt
  • /lint.jar
  • /api.jar
  • /public.txt(官方文档将其定义为必须包含,实测是可以不包含的)

AAR文件组成概览

三、SDK包大小与集成增量

首先我们要区分一下这两个概念:

**SDK包大小:**是指SDK包如AAR文件的大小,所占体积;

**SDK集成增量:**是指APK集成AAR后的增量,也就是集成前后的APK体积差值。

这里可以明确的是:集成AAR后的APK体积**<集成AAR前的APK体积+**AAR体积。举个例子:假如AAR有30M,APP集成该AAR后的增量一般都不会超过30M。而增量具体多少,跟主工程的实际资源或者依赖配置有关。而另一种可能,某些AAR只能支持一种ABI,集成时为了适配而修改了配置,最终反而使得整个APK的体积变小。

因此,为了科普这一概念,不妨在SDK文档或产品说明中备注SDK包大小以及预估的集成增量。对于APK大小敏感的用户就可以有一些心理准备。

四、SDK开发中的资源压缩与优化思路

正如前言所说,本文无意罗列网文提及的所有压缩优化方案,更多笔墨在于SDK开发场景下的简单可行有效果的优化思路,以及针对SDK进行配置时潜在的那些坑。

4.1、常规编译配置

资源优化与压缩的常规做法就是开启压缩、混淆和优化功能。区别于app模块,library模块不能开启shrinkResources的,这个编译器会有提示:Resource shrinker cannot be used for libraries.

android {
        buildTypes {
            //注意,以下配置仅对项目的release版本生效,需注意调试时配置区别造成的版本差异问题
            release {
                // 开启代码压缩,混淆和优化。
                minifyEnabled true
                // 开启资源缩减,需要注意的是,library模块不能开启这一选项。
                shrinkResources true
                //默认加载的ProGuard规则文件,可以在这里加入自定义文件,或在proguard-rules.pro中配置排除的规则
                proguardFiles getDefaultProguardFile(
                        'proguard-android-optimize.txt'),
                        'proguard-rules.pro'
            }
        }
        ...
    }

4.2、资源压缩与原生类库配置

4.2.1、资源文件压缩

资源文件指的是类似于:图片、音频、视频等多媒体资源,这些资源都可以进行一定程度的压缩优化。并且,如果你的项目未曾做过类似优化,简单处理即可出效果。

针对图片、音频、视频的压缩、替换网络上都有非常多的成熟方案,这里就不再一一提及了。

4.2.2、精简原生类库

按需配置jniLibs下保留的ABI目录,如:armeabi-v7a、arm64-v8a

defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a' //指定支持的ABIs
        }
        ...
    }

在SDK的开发与集成中,如果你的代码包含SO库,那么这个配置非常重要。由于不同的组件可能有不同的jniLibs目录,如果不加以限制,那么打包时就会将不完整的目录打包进去,导致App崩溃。

举个例子:

原App工程中只支持armeabi-v7a(由于目录删的够干净,gradle不配置也没问题),此时若新增集成了一个包含armeabi-v7a,arm64-v8a两种ABI的AAR,却并没有在gradle配置中限定需要支持的ABIs,那打出来的APK就会存在两份SO文件,但只有armeabi-v7a文件夹下的SO是齐全的。这个APK在被支持arm64-v8a的手机加载时,就会默认去检索arm64-v8a目录下的SO,因为找不到原App相关的SO模块,程序就崩溃了。

五、结语

本篇简单介绍了SDK的文件组成、体积控制、优化方面的知识,以及在SDK开发与集成时需要注意的压缩优化配置,希望唤起开发者对于SDK包体积与集成增量的感性认知与优化意识,为探索如何开发一个优秀的SDK提供一些思路。项目优化来源于外部需求,更来源于开发者自身的认知与意识。

最后,如果本篇文档对您的开发有所帮助或启发,点赞/关注/分享三连就是对作者持续创作最好的激励,感谢支持!

参考文章

版权声明:

本文首发于我的专栏 AndDev安卓开发 已授权鸿洋公众号独家发布。