随着项目的不断迭代,功能越来越多,构建出来的apk文件的大小也会越来越大,这样会导致在移动网络情况下下载时,使用的网络流量会增大,并且apk太大,导致下载的时间也增加,虽然当前每个人的手机的流量都很多,对用户流量影响不大,但是据一些网站统计,安装包越大,用户的转化率是在降低的,所以减少apk的体积,可以让更多的用户愿意去下载和体验产品。所以,对apk体积进行瘦身还是很有必要的。在对apk体积进行瘦身前,最好保证这个apk已经是经过Proguard优化过的。
经过了Proguard对apk进行压缩,优化,混淆后,在去对这个已经进行优化过的apk进行瘦身更有意义。
下面是项目总常用的对apk进行优化的方式:
在app的主module下的gradle文件中做如下配置
buildTypes {
release {
//开启代码混淆
minifyEnabled true
//Zipalign优化
zipAlignEnabled true
//移除无用的resource文件
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
使用 shrinkResources 进行移除,配合 //Zipalign优化
使用 shrinkResources 必须先开启代码混淆 minifyEnabled
关于混淆相关的配置,不是本文重点,下面进行简单介绍
proguard-android.txt文件中的常用的混淆配置信息如下:
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.
-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native ;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
-keepclassmembers class **.R$* {
public static ;
}
# The support library contains references to newer platform versions.
# Dont warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**
-dontusemixedcaseclassnames 表示混淆时不使用大小写混合类名。
-dontskipnonpubliclibraryclasses 表示不跳过library中的非public的类。
-verbose 表示打印混淆的详细信息。
-dontoptimize 表示不进行优化,建议使用此选项,因为根据proguard-android-optimize.txt中的描述,
优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行
-dontpreverify 表示不进行预校验。这个预校验是作用在Java平台上的,Android平台上不需要这项功能,
去掉之后还可以加快混淆速度。
-keepattributes Annotation 表示对注解中的参数进行保留。
更多关于proguard混淆规则的介绍,请参考Android安全攻防战,反编译与混淆技术完全解析(下)
defaultConfig {
...
//只保留指定和默认的资源
//resConfigs('zh-rCN','ko')
resConfigs "zh"
}
经过上面的配置后,打包出的apk,在进行apk的分析,这样效果会更好。Android studio 从2.2开始就提供了分析apk文件的功能,在Android Studio工具栏里,打开build–>Analyze APK, 选择要分析的APK包,或者直接将apk包拖到AS中。下图是对apk分析的结果:
但是在看上面这个图之前,需要先了解各个部分的含义:
通过上图中对apk文件中各个部分的文件占比的分析,可以看到占用空间的主要是代码、图片、资源和lib和assert文件,主要方向精简代码、压缩图片、去除无用的库、减少asserts里面文件。
```
//配置so库架构(真机: arm ,模拟器 x86 )
defaultConfig {
...
ndk {
//abiFilters "armeabi", "armeabi-v7a"
abiFilters 'armeabi-v7a'
}
}
```
完成这个步骤后,就可以看到,apk包中的lib中,只剩下armeabi-v7a文件夹中的so文件了。
重新编译so文件,用更小的库代替
很多第三方我们导入进来只用到其中很小一部分功能,大部分功能都是我们用不上的。这时候我们找到源代码,将我们需要的那部分代码提取出来,重新编译成新的so文件,再导入到我们项目中。
通过插件化,动态加载so库文件。
手动lint检查,手动删除无用的资源文件。
版本迭代过程中,不但有废弃代码冗余,肯定会有无用的图片存在。在build.gradle 里面配置shrinkResources true,在打包的时候会自动清除掉无用的资源,但经过实验发现打出的包并不会,而是会把部分无用资源用更小的东西代替掉。注意,这里的“无用”是指调用图片的所有父级函数最终是废弃代码,而shrinkResources true 只能去除没有任何父函数调用的情况,真正起效果只能通过Android Studio自带的 “Remove Unused Resources”小插件来实现了。更人性化是该查找结果可以“一键删除”。当然,可能图片是经过反射或字符拼接等方式获取,所以这个检测列表也不是全对,删除后很大概率编译失败或部分页面挂死、无图等问题,这个无解,工具还没智能到这个地步,你只能一遍又一遍“编译—解决部分问题—再编译再”。
使用tinypng等图片压缩工具对图片进行压缩
TinyPNG工具只支持上传PNG图片到官网上压缩,然后下载保存,在保持alpha通道的情况下对PNG的压缩可以达到1/3之内,而且用肉眼基本上分辨不出压缩的损失.。
Tinypng的官方网站:http://tinypng.com/
大部分的图片使用webp格式替代
webp支持透明度,压缩比比jpg更高但显示效果却不输于jpg,官方评测quality参数等于75均衡最佳。相对于jpg、png,webp作为一种新的图片格式,限于android的支持情况暂时还没用在手机端广泛应用起来。从Android 4.0+开始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持显示含透明度的webp,使用的时候要特别注意。
官方介绍:https://developers.google.com/speed/webp/docs/precompiled
尽量少使用帧动画,帧动画需要的图片较多,并且很占内存,建议使用属性动画替代。
使用一套资源
对于绝大对数APP来说,只需要取一套设计图就足够了。鉴于现在分辨率的趋势,建议取1080p的资源,放到xxhdpi目录,在加上一些屏幕适配的处理,基本能够适配大部分的手机。相对于多套资源,只使用1080P的一套资源,在视觉上差别不大,很多大公司的产品也是如此,但却能显著的减少资源占用大小,顺便也能减轻设计师的出图工作量了。
使用jpg格式
如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止。在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择。
缩小大图
如果经过上述步骤之后,你的工程里面还有一些大图,考虑是否有必要维持这样的大尺寸,是否能适当的缩小。
事实上,由于设计师出图的原因,我们拿到的很多图片完全可以适当的缩小而对视觉影响是极小的。
覆盖第三库里的大图
有些第三库里引用了一些大图但是实际上并不会被我们用到,就可以考虑用1x1的透明图片覆盖。你可能会有点不舒服,因为你的drawable下竟然包含了一些莫名其妙的名称的1x1图片
使用微信资源压缩打包工具(AndResGuard)
矢量图
矢量图是由点与线组成,和位图不一样,它再放大也能保持清晰度,而且使用矢量图比位图设计方案能节约30~40%的空间,现在谷歌一直在强调扁平化方式,矢量图可很好的契合该设计理念。
优势
(1)占用存储空间小
(2) 无极拉伸不会出现锯齿,可以照顾不同尺寸的机型
(3)Android Studio自带很多资源,减小UI工作量
劣势
(1) 只支持5.0及以上系统
(2) 与位图相比多了一层计算,需消耗更多性能
(3) 不支持.9图
(4)不适合表现真实照片和复杂图形,一般使用在简单的icon和动画上
实现:
在app的build.graldle中的defaultConfig 标签下:
defaultConfig {
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//minSdkVersion 19 (5.0)
vectorDrawables.generatedDensities('xhdpi','xxhdpi','xxxhdpi')
//minSdkVersion > 19
// vectorDrawables.useSupportLibrary = true
}
使用shape背景
特别是在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了大量的背景图片。
使用着色方案
相信你的工程里也有很多selector文件,也有很多相似的图片只是颜色不同,通过着色方案我们能大大减轻这样的工作量,减少这样的文件。借助于android support库可实现一个全版本兼容的着色方案,
加上一行代码 android:tint="@color/colorAccent"
线化素材库
如果你的APP支持素材库(比如聊天表情库)的话,考虑在线加载模式,因为往往素材库都有不小的体积。这一步需要开发者实现在线加载,一方面增加代码的复杂度,一方面提高了APP的流量消耗,建议酌情选择。
这个部分的优化,就需要优化.class文件的大小了,可以从以下几个方面入手:
参考:
Android性能优化系列之apk瘦身
https://blog.csdn.net/u012124438/article/details/54958757
Android 性能优化系列:APK极致优化
https://mobile.51cto.com/abased-600232.htm
Android性能优化之APK瘦身详解(瘦身73%)
https://blog.csdn.net/qq_32175491/article/details/80071987
Android 图片着色 Tint 详解
https://www.cnblogs.com/Free-Thinker/p/9105288.html
Android-使用tint一张图制作selector
https://blog.csdn.net/Blizzard_liu/article/details/52689688
AndResGuard集成笔记
https://www.jianshu.com/p/fe988af9c663
redex, Android应用的字节码优化器
https://www.helplib.com/GitHub/article_138303