Gradle从入门到了解 - 简书

作者:hongjay

地址:http://www.jianshu.com/p/88fb3876d92d

声明:本文是hongjay原创,已获其授权发布,未经原作者允许请勿转载

通过这篇文章,你可以了解到以下内容:

1、在自己的项目中使用脚本准备起飞。一次打包十几个项目不嫌累。

2、面对下载下来的开源项目编译报错有一定处理能力。

3、水群吹牛逼直起腰板。

Gradle概述

Gradle(英[g'reɪdl])是一个任务驱动型的构建工具,是一个依赖管理工具,更是一个编程框架。 它抛弃了基于XML的各种繁琐配置,取而代之的是一种基于Groovy的内部领域特定(DSL)语言。 在android studio中,我们使用这个工具可以完成app的编译打包等工作。

Goals of the new Build System(使用gradle的目的)

1、Make it easy to reuse code and resources

2、Make it easy to create several variants of an application, either for multi-3、apk distribution or for different flavors of an application

4、Make it easy to configure, extend and customize the build process

Good IDE integration

采用Gradle作为新构建系统的目标:

1、让重用代码和资源变得更加容易。

2、让创建同一应用程序的不同版本变得更加容易,无论是多个apk发布版本还是同 一个应用的不同定制版本。

3、让构建过程变得更加容易配置,扩展和定制。

4、更好的IDE集成。

Gradle Android插件用户指南翻译

Gradle Plugin User Guide 官方原文地址

http://tools.android.com/tech-docs/new-build-system/user-guide

中文版在线阅读地址

http://avatarqing.github.io/Gradle-Plugin-User-Guide-Chinese-Verision

简单来说有以下几点

1、独立项目,和Google无关

2、Gradle基于Groovy。(Maven、Ant基于xml)Groovy是拓展了Java语言的 一种动态语言,语法更简洁,可以作为Java平台的脚本语言使用 ,拥有类 似Python、Ruby和Smalltalk中的一些特性。

Gradle是基于Groovy定义了一套DSL,所谓DSL(领域专用语言),就是专门 针对某一特定问题的计算机语言。而Gradle我们可以认为是经过“定制”的 Groovy,专门用于项目构建的语言。

2、Gradle兼容Maven、Ant

4、Gradle 的推出主要以 Java 应用为主,当然还支持 Android、C、C++等。

Gradle基本组件

每一个build.gradle文件代表着一个Project。Tasks在build.gradle中定义。当初始化构建进程时,gradle会基于build文件,集合所有的Project和Tasks,一个Tasks包含了一系列动作,然后它们将会按照顺序执行,一个动作就是一段被执行的代码,很像Java中的方法。

  • Project 每一个待编译的工程(可以是一个jar包,一个web应用,或者一个android app等)都称为一个Project。
  • Task 每一个Project在构建的时候都包含一系列的Task。一个Task其实就是构建过程中一个原子性的操作。比如一个Android APK的编译可能包含:Java源码编译Task、资源编译Task、JNI编译Task、lint检查Task、打包生成APK的Task、签名Task等。
  • Plugin Gradle是一个框架,作为框架,它负责定义流程和规则。而具体的编译工作则是通过插件的方式来完成的。比如编译Java有Java插件,编译Groovy有Groovy插件,编译Android APP有Android APP插件,编译Android Library有Android Library插件。 简单来说,插件就是一系列任务的集合,主要作用是把一些重复利用的逻辑打包,这样就可以在不同的项目中可以重复的使用。 要使用插件,可以通过引入依赖的方式添加。

As如何依赖Gradle让Gradle作为自身的构建工具呢?

答:Google开发了一个Gradle插件,让As项目依赖这个插件,就相当于让Gradle作为自身的的构建工具。

现在比如我们新建一个As项目,打开项目的根目录的gradle.build文件。有如下代码:

而要引入Android APP插件,就需要在build.gradle引用Android APP插件:

Android其实就是写了两个插件:

1、com.android.application

2、com.android.library

应用这两个插件就可以实现Android APP和Android Library的构建。

As项目中的Gradle

.gradle文件夹

.gradle文件夹 是gradle 运行以后生成的缓存文件夹。

Project中的build.gradle文件

project下的build.gradle是基于整个project的配置,主要配置gradle 版本及 全局依赖仓库、库或者其他全部参数。

module中build.gradle文件

Project中setting.gradle

这个文件是全局的项目配置文件,里面主要声明Project中所包括的所有module

Project中gradle.properties

gradle.properties为gradle的配置文件,里面可以定义一些常量供build.gradle使用,比如可以配置签名相关信息如keystore位置,密码,keyalias等,build.gradle就可以直接引用gradle 中的一些配置参数建议写到gradle.properties

配置应用的签名信息

在android.signingConfigs{}下定义一个或者多个签名信息,然后在buildTypes{}配置使用即可。比如这里:

storeFile是签名证书文件,keyAlias是别名,keyPassword是key的密码,storePassword是证书的密码。配置好相关信息即可在buildTypes配置使用。

一般重要的信息,例如签名信息,可以直接将信息写到gradle.properties,然后在然后在build.gradle中引用即可。

buildTypes是指建构的类型,一般只用两种默认类型 debug 和 release ,顾名思义 debug 用来配置开发过程中的一些内容;release 用来配置正式发布版本的内容。有时我们需要发布介于debug与release之间的preview 版本。

Build Variant 差异管理

比如app生成不同版本(免费,收费),适配特殊机型,多渠道等需要发多个包,最终能编译出的apk的数量是由Product Flavor(产品种类)与Build Type(构建类型)决定的, 公式:Build Variant = Build Type x Product Flavor

BuildType(构建类型)

默认有debug和release两种,标示编译的类型,通常在混淆代码、可调式、资源压缩上做一些区分。

Product Flavor(产品种类)

为了满足“同一个project,根据一个很小的区分,来打不同的包”这个需求。实现多渠道打包。注意:这里的Flavor名如果是数字开头,必须用引号引起来。

调整module的目录结构sourceSets

默认情况下,java文件和resource文件分别在src/main/java和src/main/res目录下,在build.gradle文件的andorid{}里面添加下面的代码,便可以将java文件和resource文件放到src/java和src/resources目录下。

全局变量定义及引用

可以在顶层build.gradle脚本中定义一些全局变量,提供给子脚本引用:

子脚本引用:

Gradle常用命令介绍

打开Android Studio内置的Terminal终端,输入如下命令:

gradlew代表 gradle wrapper,意思是gradle的一层包装,大家可以理解为在这个项目本地就封装了gradle,即gradle wrapper。 在./gradle/wrapper/gralde-wrapper.properties文件中声明了它指向的目录和版本。只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。

assemble 命令创建task有如下语法:

1、允许直接构建一个Variant版本,例如assembleFlavor1Debug。

2、允许构建指定Build Type的所有APK,例如assembleDebug将会构建Flavor1Debug和Flavor2Debug两个Variant版本。

3、允许构建指定flavor的所有APK,例如assembleFlavor1将会构建Flavor1Debug和Flavor1Release两个Variant版本。

批量修改生成的apk文件名

在我们打包发版的时候,一次性打几十个包,这时候我们就想让生成的apk文件名有区分,比如一眼就能看出这个apk是哪个版本的,哪个渠道的,是哪天打的包等等,这就需要我们在生成apk文件的时候动态修改生成的apk文件名达到这一目的。代码如下:

以baidu渠道为例,以上的代码会生成一个名字为Gtobus__gotobus_v5.1.2_20161115.apk安装包。

这里是循环处理每个applicationVariant,当他们的输出文件名以apk结尾并且buildType是release时,重新设置新的输出文件名,这样就达到了我们批量修改生成的文件名的目的。

项目中的问题

android studio的编译时屏蔽掉lint检查,可以避免由于编译条件太过严格而编译不过的问题:

如果遇到多个jar包中的某个文件冲突,可以在对应module下的build.gradle文件的android标签下加上如下属性:

依赖版本冲突

依赖冲突是所以依赖管理中最头痛的问题,这常常出现在传递依赖中。Gradle对解决传递依赖提供了两种策略,使用最新版本或者直接导致构建失败。默认的策略是使用最新版本。虽然这样的策略能够解决一些问题,但是还是不够。常见的一种情况是,NoSuchMethond或者ClassNotFound。这时候,你可能需要一些特殊手段,比如排除不想要的传递依赖。

排除传递依赖

排除传递依赖有多种原因,远程仓库中不存在,运行时不需要,或者版本冲突。排除传递依赖的方式有两种:1.直接在configuration中排除 2.在具体的某个dependency中排除。

错误:Execution failed for task ':app:transformClassesWithDexForDebug'.

com.android.build.api.transform.TransformException:

java.lang.RuntimeException:

com.android.ide.common.process.ProcessException:

java.util.concurrent.ExecutionException:

com.android.ide.common.process.ProcessException:

org.gradle.process.internal.ExecException: Process 'command

'D:\Java\jdk1.8.0_31\bin\java.exe'' finished with non-zero exit value 1

上面都是扯淡,下面才是重点!!!

替换AndroidManifest中的占位符

运行时修改静态变量

在build.gradle中配置buildConfigField参数,编译后会在..\app\build\generated\source\buildConfig文件夹下会自动生成对应版本对应module的BuildConfig.java。 BuildConfig就会包含对应版本的配置信息。程序中可以直接引用这些数据。需要注意的是BuildConfig定义的变量实在当前module下,如果还有一个基础module需要直接在基础module的gradle下配置。

buildConfigField "String", "APPNAME_GOTOBUS", '"coachrun"'


//使用举例
static{    
        APPNAME= BuildConfig.APPNAME_GOTOBUS;
}

运行时修改strings.xml数据

resValue "string", "app_name", "GotoBus"

// 在Activity里调用
getString(R.string.app_name) // 输出GotoBus

运行时修改颜色

//使用和字符串相似
resValue "color", "flavor_color", "#0000ff"

资源文件和manifest的合并

在打包app之前,Android插件会合并main中的代码和构建的代码。当然,依赖项目也可以提供额外的资源,它们也会被合并。你可能需要额外的Android权限针对debug变体。举个例子,你不想在main中申明这个权限,因为这可能导致一些问题,所以你可以添加一个额外的mainfest文件在debug的文件夹中,申明额外的权限。

资源和mainfests的优先级是这样的:

如果一个资源在main中和在flavor中定义了,那么那个在flavor中的资源有更高的优先级。这样那个在flavor文件夹中的资源将会被打包到apk。而在依赖项目申明的资源总是拥有最低优先级。

Gradle编译优化

1、在添加依赖的时候尽量明确版本号,省去gradle查找最新版的时间

不要使用
compile ‘com.facebook.fresco:fresco:latest’ 
compile ‘com.facebook.fresco:fresco:1.+’,

2、使用daemon

构建初始化的很多工作是关于java虚拟机的启动,加载虚拟机环境,加载class文件等,如果这些动作交给一个单独的后台进程去做,那么,第一次初始化之后的修改代码再构建是不是可以节省很多时间呢?答案是肯定的,通过在gradle.properties加入这样一句来开启,如果想让修改全局所有项目都生效,那么修改这个文件~/.gradle/gradle.properties

org.gradle.daemon=true

3、并行构建模块化项目

将你的项目拆分成多个子项目并开启并行构建也是一个不错的主意,比如将相对独立的模块拆分成独立的库工程(Library projects),主工程(Application project)依赖这些库工程,这样的话,开启并行构建才会发挥作用。并行构建开启方式是修改文件gradle.properties,加入如下行:

org.gradle.parallel=true

参考

http://www.jianshu.com/p/01281d1c3384

http://www.cnblogs.com/Bugtags2015/p/5563427.html

https://www.figotan.org/2016/04/01/gradle-on-android-best-practise/

http://www.jianshu.com/p/9dcec4a14c52#

原文发布于微信公众号 - Android先生(cyg_24kshign)

原文发表时间:2017-09-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张伟博客

windows7 下,在CMD命令模式下,如何添加永久路由?

双网卡之间互相访问原理其实很简单,互相设置对方的IP为自己的这张网卡的网关就足够了。为了让机器重启动后依然有效,在使用route 命令添加路由的时候加上 -p ...

1.2K10
来自专栏小狼的世界

在Centos 5.2下编译安装LAMP

首先使用Virtualbox安装一台CentOS 5.2的虚拟机,网络连接采用 Host-only Adapter,这样主客机之间可以互相访问,但是客机不能够上...

11220
来自专栏Seebug漏洞平台

GNU tar 解压路径绕过漏洞(CVE-2016-6321) 分析

Author: LG (知道创宇404安全实验室) 漏洞简介 GNU tar文档管理命令是linux系统下常用的一个打包、压缩的命令。经CSS(FSC1V Cy...

39660
来自专栏互联网杂技

SpringBoot (一) :入门篇

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而...

12630
来自专栏Hadoop实操

HDFS添加 NFS Gateway 角色实例启动失败问题及解决办法

昨天登录公司测试集群的时候,发现HDFS存在告警信息,查看详细信息,发现 NFS Gateway 进程退出,尝试重启该角色实例,执行重启操作后,报如下异常:

1.7K40
来自专栏小狼的世界

Fedora下Zend Studio 6.1.2 的配置

Zend Studio是我们PHPer的一个非常的得力的工具,有了他往往能够让我们的工作事倍功半,今天就来记录一下日常使用中非常有用的配置,来帮助更多的PHPe...

10220
来自专栏散尽浮华

php安全配置记录和常见错误梳理

通常部署完php环境后会进行一些安全设置,除了熟悉各种php漏洞外,还可以通过配置php.ini来加固PHP的运行环境,PHP官方也曾经多次修改php.ini的...

50470
来自专栏Netkiller

PHP 安全与性能

PHP 安全与性能 摘要 我的系列文档 Netkiller Architect 手札Netkiller Developer 手札Netkiller PHP 手札...

50860
来自专栏曾倩倩的专栏

su命令cannot set groups: Operation not permitted的解决方法

问题场景: user_00@hadoop-10-125-224-102:> su root Password: su: cannot set groups:...

71980
来自专栏惨绿少年

KICKSTART无人值守安装

1.1 环境说明 [root@test ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [roo...

30400

扫码关注云+社区

领取腾讯云代金券