性能优化 -- APK大小减负
target:
了解APK的结构组成,及常用的缩减 APK 体积的方法。
一、APK的结构组成:
APK 文件由 Zip 压缩文件组成,包含应用相关的所有文件,如:Java类、资源文件、已编译资源文件。具体组成如下图:
APK 目录存放内容:
META-INF/: 包含 CERT.SF 和 CERT.RSA签名文件,及 MANIFEST.MF 清单文件;
assets/: 包含应用的资源;可使用 AssetsManager 获取这些资源;
res/: 包含未编译到 resources.arsc 中的资源(图片、音视频等);
lib/: 包含特定处理器软件层的已编译代码;此目录包含每种平台类型的子目录,如 armeabi 、 armeabi-v7a 、 arm64-v8a 、 x86 、 x86_64 和 mips ;
resources.arsc: 包含已编译的资源。此文件包含 res/values/文件夹的所有配置中的 XML 内容。打包工具会提取此 XML 内容,将其编译为二进制文件形式,并压缩内容。此内容包括语言字符串和样式,以及未直接包含在 resources.arsc 文件中的内容(例如布局文件和图片)的路径;
classes.dex: 包含以 Dalvik/ART 虚拟机执行的 dex文件编译的类(java 类);
AndroidManifest.xml:(必需的文件),其内包含应用的名称、版本、访问权限和引用的库文件,为二进制XML格式。
二、APK瘦身方式:
APK 瘦身有以下几种方式:
- 方法一:使用 Android Size Analyzer 插件;
- 方法二:Gradle 中开启 shrinkResources,自动移除未使用的资源(未使用资源不会打包进 apk);
- 方法三:使用 Lint 工具;
- 方法四:删除未使用的备用资源;
- 方法五: 针对 不同库文件(so文件)分别打包 APK。
三、具体使用:
1、使用 Android Size Analyzer 插件
option:
a、在studio中安装下载 Android Size Analyzer 插件;
b、菜单栏选择 studio menu --> Analyze --> Analyze App Size ,对当前应用进行大小分析,根据分析结果建议进行相关优化操作。
分析结果如下:
note:之前在 studio 低版本中用过此插件,当前使用 studio 3.5 未找到,也可能在更高版本中会出现。
2、Gradle 中开启 shrinkResources
开启 Gradle 的 shrinkResources 功能后,不会将未使用的资源文件 打包进 APK。使用的同时,要使用代码混淆(点我跳转),即配置 minifyEnabled 为 true,具体可参看 。
Note:如果项目中有 反射进行引用资源,则也会被忽略。
android {
// Other settings
buildTypes {
release {
minifyEnabled true
//TODO 忽略未使用的资源
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
针对设置 shrinkResources true 忽略未使用资源,而导致使用反射的资源也被忽略的问题,可以使用【自定义保留资源】的方式,具体 option 见下文。
3、使用 Lint 工具
- option:
studio menu --> Run Inspection By Name --> 录入 unused resource
note:此处删除的未使用的资源为本地项目文件,请谨慎操作。
4、删除未使用的备用资源
Gradle 中开启 shrinkResources 只能忽略 未被引用的资源,但不会溢出用于不同设备配置的 备用资源,如:语言(中英文)。此时,可通过 Gradle 的 resConfigs 属性溢出不需要的资源:
android {
defaultConfig {
targetSdkVersion 30
...
//TODO 只保留中文
// resConfigs "zh-rCN"
}
}
5、自定义保留资源文件
对于第二种情况【Gradle 中开启 shrinkResources】导致被反射引用的资源也被忽略的问题,可以使用 自定义保留资源文件的方式来解决。
- option:
在 res 目录下创建 raw 文件夹;
创建 名为 keep.xml 文件;
在 res/raw/keep.xml 中添加要保留/移除的资源
<?xml version="1.0" encoding="utf-8"?>
<!-- TODO keep 中放置需要保存的资源
discard 中指定要舍弃的资源,使用逗号隔开
note: 可以使用 通配符保留/删除多个资源
-->
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@drawable/unuse_res_call_expert"
/>
6、针对 不同库文件(so文件)分别打包 APK
so 文件是由 ndk 编译的动态库,c/c++编写,不可跨平台。
ABI 是应用程序二进制接口的检测,定义二进制文件如何运行在相应的系统平台上。
Android 系统中,每一个 CPU 架构对应一个 ABI,目前支持armeabi-v7a、arm64-v8a、x86、x86_64,当前基本是 arm 架构。如果so文件库有限,可考虑只配置 armeabi-v7a。
android {
defaultConfig {
...
ndk{
abiFilters "armeabi-v7a"
}
}
}
同时,也可以使用 ProduceFlavor 和 splits 来实现 APK 的分包【flag:后期增加使用 Variants 打包】,如下:
7、其他:
- 小图标使用 矢量图
- 使用 webp 格式图片
相关链接: