高级自定义构建
- 减少APK文件的大小
- ProGuard
- 缩减资源
- 自动缩减
- 手动缩减
- 加速构建
- Gradle参数
- Profiling
- 忽略Lint
- 在Gradle中使用Ant
减少APK文件的大小
在过去几年中,APK文件的大小曾成急剧增长态势。一般来说,其原因如下:Android开发者获取了更多的依赖库,添加了更多的密度,Apps增加了更多的功能。
但实际上我们应该让APKs尽可能的小。不仅是因为在Google Play中,APK文件有50MB的限制,而且更小的APK意味着用户可以更快的下载和安装应用,并使它占用更小的内存。
下面我们研究如何设置Gradle构建配置文件中的几个属性,以缩小APK文件。
ProGuard
ProGuard是一个Java工具,其不仅可以缩减APK文件的大小,还可以在编译期优化,混淆和预校验你的代码。其通过你应用的所有代码路径,来找到为被使用的代码,并将其删除。ProGuard还会重命名你的类和字段。这一过程将保留应用的踪迹,让反编译工程师更加难以读懂代码。
在Gradle的Android插件中,其构建类型下面有一个叫作minifyEnabled的布尔类型属性,你需要将它设置为true来激活ProGuard:
android{
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
当minifyEnabled被设置为true后,在构建过程中,proguardRelease task会被执行,并调用ProGuard。
再激活ProGuard之后,应重新测试整个应用,因为ProGuard可能会移除一些你仍需要使用的代码。这也是很多开发者不喜欢ProGard的原因。为了解决这个问题,你可以定义ProGuard规则,派出那些被删除或者混淆的类。我们可以使用proguardFiles属性来定义包含ProGuard规则的文件。例如,为了保留一个类,你可以像下面这样添加一条简单的规则:
-keep public class < MyClass>
getDefaultProguardFile(‘proguard-android.txt’)方法从Android SDK的tools/proguard文件夹下的proguard-android.txt文件中获取默认的ProGuard设置。在Android Studio中,proguard-rules.pro文件被默认添加到新的Android模块,所以你可以在该文件中简单的添加一些针对该模块的规则。
除了缩减Java代码外,还可以缩减使用过的资源。
缩减资源
当给App打包时,Gradle和Gradle的Android插件可以在构建期间删除所有未使用的资源。如果你有旧的资源忘记删除,那么这个功能可能非常有用。另外一个使用案例是当你导入一个拥有很多资源的依赖库,而你只是用了其中的一小部分时,你可以哦通过计划缩减资源来解决这一问题。酸碱资源的方式有两种:自动和手动。
自动缩减
最简单的方式是在你的构建中设置shrinkResorces属性。如果设置该属性为true,则Android构建工具将自动判断哪些资源没有被使用到,并将他们排除在APK外。
使用此功能有一个要求,即必须同时启动ProGuard。这是因为缩减资源的工作方式是,直到代码引用这些资源被删除之前,Android构建工具不能之处哪些资源没有被用到。
下面的代码片段展示了在某个构建类型中,如何配置自动化资源缩减:
android{
buildTypes {
release {
minifyEnabled true
shrinkResources true
}
}
}
如果你想看看再激活了自动化资源缩减之后,APK缩减了多少,则可以运行shrinkReleaseResources任务。该任务会打印除报得大小缩减了多少。
手动缩减
去除某种语言文件或某个密度的图片,是删减资源的一种比较好的方式。一些依赖库,例如Google Play Services,其包含了多种语言。如果你的应用只支持一两种语言,那么再最终的APK中,包含所有语言的文件就会浪费许多资源。这时你就可以使用resConfigs属性来配置你想保留的资源,将其余部分删除。
如果你只想保留英语,则可以这样使用resConfigs:
android{
defaultConfig{
resConfigs "en"
}
}
多种语言用逗号隔开
你也可以这样处理密度集合:
android{
defaultConfig{
resConfigs "hdpi","xhdpi"
}
}
你甚至可以结合语言和密度。实际上,使用此属性可以限制每一种类型的资源。
如果设置ProGuard让你感觉很困难,或者你仅仅想再应用中去除不支持的语言资源或密度,那么你可以使用resConfigs来缩减资源。
加速构建
很多Android开发者再开始使用Gradle的时候,都会抱怨编译时间过长。和Ant相比,用Gradle构建需要更长的时间,因为你每执行一个任务时,Gradle都要构建生命周期中的三个阶段。这使得整个过程非常方便配置,但是页相当的缓慢。
Gradle参数
加速Gradle构建的一种方式是改变一些默认的配置。你可以通过在根目录下的gradle.properties文件中设置一个属性来启动并行构建,只需添加下面一行代码即可:
org.gradle.parallel=true
另外一种方式是启动Gradle daemon,其会在你第一次运行构建时,开启一个守护进程。任何后续构建都将复用该守护进程,从而减少启动成本。只要你使用Gradle,该进程就一直存活,并且在空闲三个小时后终止。当你在很短的时间内多次使用Gradle时,使用daemon会非常有用。在gradle.properties文件中启动daemon的代码如下:
org.gradle.daemon=true
在Android Studio中,Gradle daemon时默认开启的。这意味着IDE内部的第一次构建后,下一次构建会快一些。然而如果你是通过命令行来构建界面的,则Gradle daemon是关闭的,除非你在配种中启动它。
你可以调整Java虚拟机的参数来加速编译。Gradle有一个叫作jvmargs的属性可以让你为jvm的内存分配池设置不同的值。对构建速度有直接影响的两个参数是Xms和Xmx。Xms参数用来设置初始内存大小,Xmx用来设置最大内存。你可以在gradle.properties文件中,手动设置这些值:
org.gradle.jvmargs=-Xms256m -Xmx1024m
最后一个可以用来影响构建速度的可配置属性是org.gradle.configureondemand。如果你的项目中有多个模块,那么该属性会非常有用,因为,他会忽略正在执行的task不需要的模块来限制在配置阶段的时间消耗。如果你设置该属性为true,则Gradle将在运行配置阶段前,指出哪一个模块有配置改变,哪一个没有。当你的项目中只有一个Android应用和一个依赖库时,该特性没有任何用处。如果你的项目中有很多松散耦合的模块,那么该属性会为你节省大量的构建时间。
Profiling
如果你想找到构建中让速度变慢的具体位置,则可以拆分整个构建过程。当执行一个Gradle任务时,你可以通过添加–profile标志来实现这一点。当你提供了该标志时,Gradle会创建一份分拆报告,其会告诉你构建过程中究竟哪一部分最为耗时。一旦知道瓶颈在哪里,你就可以进行必要的修改。报告最终会被保存为一份HTML文件,存放在你的模块中的build/reports/profile下。
忽略Lint
当你通过Gradle执行一个release构建时,你的代码中会执行一个Lint检查。Lint是一种静态代码分析工具,他会在你的布局和Java代码中标记潜在的bug。在默写情况下,甚至会阻塞构建过程。如果你之前在项目中从未使用Lint,而现在想将项目迁移至Gradle,那么Lint可能出现很多错误。为了让构建能够正常工作,你可以禁用abortONError,让Gradle忽略Lint错误,防止他们影响构建。这只是一个临时的解决方案,因为忽略Lint错误会导致一些问题,如缺失翻译,会直接导致应用崩溃。为了防止Lint阻塞构建过程,应像下面这样禁用abortOnError:
android{
lintOptions{
abortOnError false
}
}
临时禁用Lint异常终止,使得从一个已存在的Ant构建过程迁移到Gradle变得更加容易。另外一个让过渡更加平滑的方式是直接在Gradle中执行Ant任务。
在Gradle中使用Ant
如果你在设置Ant构建过程中投入了大量时间,那么切换到Gradle听起来可能很不可思议。在这种情况下,Gradle不仅可以执行Ant任务,还可以扩展他们。这意味着,你可以一步步从Ant迁移到FGradle,而不是在改造整个构建配置种花费数天时间。
Gradle使用Groovy的AntBuilder来进行Ant整合。AntBuilder允许你执行任何标准的Ant任务,自定义Ant任务和整个Ant构建。这也使得你可以在Gradle构建配置中定义Ant属性。