为什么要对apk包体积进行优化?
体积越大,下载流量大,安装时间长,在竞品中低体积包更容易获取用户;ROM厂商会有一些内置的应用,由于内存较小,需要优化,减少内存占用。
如何优化?
- 图片优化
首先切图上,可以使用720p(xhdpi)来适配,其次,在图片使用上,一些小图标尽量使用svg(体积最小,如果你需要支持5.0以下,建议一套png图标搞定),如果对于非透明的大图,jpg将会比png的大小有显著的优势, 在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择,其它使用png就可以了,TinyPNG工具只支持上传PNG图片到官网上压缩,然后下载保存,在保持alpha通道的情况下对PNG的压缩可以达到1/3之内,而且用肉眼基本上分辨不出压缩的损失.
Tinypng的官方网站。其他方案这个文章可以参考下:Android开发小技巧,3种类型图片带你降低包体积
- 无用资源剔除
AndroidStudio提供了一键移除未使用资源的工具,refractor->remove unused resources,但是不建议使用,因为如果资源是动态获取的,也会认为未被使用而被物理移除。如果要用,通过Lint工具,、Code->Analyze->Run inspection by name->unused resource删除。
使用shrinkResources,他不会删除源文件,只会对打包出来的apk做优化,它需要和代码混淆一起开启,因为只有先开启代码混淆(压缩),才会知道资源是否引用,才会对资源进行剔除。非严苛模式下,不会剔除Resources.getIdentifier() 动态引用的资源,严苛模式下会剔除
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:discard="@layout/shrink1"
tools:keep="@layout/shrink"
tools:shrinkMode="safe"/>
<!--discard:做严格检查-->
<!--keep :不做严格检查-->
<!--shrinkMode="strict" :该模式只保留在代码或者资源文件中明确引用的资源-->
<!--shrinkMode="safe" :该模式会保留所有明确引用的资源以及可能被 Resources.getIdentifier() 动态引用的资源-->
- 国际化资源配置优化
大部分应用其实并不需要支持几十种语言的国际化支持。还好强大的gradle支持语言的配置
android {
defaultConfig {
resConfigs 'en','zh-rCN'
}
}
- 动态库打包优化
分包:同时会打两个包
splits {
abi {
enable true
reset()
include 'armeabi-v7a',"arm64-v8a"
universalApk false
}
}
只保留armeabi-v7a
ndk {
abiFilters 'armeabi-v7a'
}
- 代码压缩优化
使用代码混淆,优化代码压缩
buildTypes {
release {
// 源代码混淆 true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
#(1)dump.txt —- 说明APK中所有类文件的内部结构
#(2)mapping.txt —- 提供原始与混淆过的类、方法和字段名称之间的转换
#(3)seeds.txt —- 列出未进行混淆的类和成员
#(4)usage.txt —- 列出从APK移除的代码
#这些文件保存在/build/outputs/mapping/release目录下。
#解码混淆过的堆叠追踪
#使用混淆后,一定要保存好mapping文件,程序csh时通过脚本进行解码。
#retrace工具位于/tools/proguard/目录中,解码命令为:
#
# retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
# 指定代码的压缩级别
-optimizationpasses 5
# # 忽略警告,避免打包时某些警告出现(慎用)
-ignorewarnings
# 混淆时不生成大小写混合的类名
-dontusemixedcaseclassnames
# 混淆第三方jar
-dontskipnonpubliclibraryclasses
# 不预先验证已处理的类文件
-dontpreverify
# 混淆运行出现异常时打印日志在控制台
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保持某个包的类不被混淆
-keep class com.umeng.** { *; }
# 保持自定义的类不被混淆
#-keep class 类名
# 保留继承了哪些类的类不被混淆
-keep public class * extends android.app.Service
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.preference.Preference
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.content.BroadcastReceiver
#-keep public class com.android.vending.licensing.ILicensingService
# 保留实现了Serializable接口方法的类不被混淆
-keepclassmembers class * implements java.io.Serializable {*;}
# 保持实现Parcelable接口方法的类不被混淆
-keepclassmembers class * implements android.os.Parcelable
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# 保持枚举 enum 类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#butterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
#Gson
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.gson.** { *;}
#这句非常重要,主要是滤掉 com.demo.demo.bean包下的所有.class文件不进行混淆编译,com.demo.demo是你的包名
-keep class com.demo.demo.bean.** {*;}
#slideMenu
-dontwarn com.jeremyfeinstein.slidingmenu.lib.**
-keep class com.jeremyfeinstein.slidingmenu.lib.**{*;}
总结
apk瘦身主要是从图片文件、代码混淆(压缩)、无用资源剔除优化、so库这几个方面来优化。
网友评论