0%

Android Gradle最佳实践系列1:Gradle快速入门及AndroidStudio介绍

在2013年的Google Io,出于更好的重用代码和自定义编译流程,Google推出了AndroidStudio和新的编译系统Gradle,AndroidStudio能使用Gradle编译,但是Gradle又能单独部署编译,更方便的做CI。如果你还没有使用AndroidStudio你可以通过Android Developer WebSite下载。
在本篇章节内容中,我们将学习如下内容:

  • 了解Android Studio
  • 了解Gradle基础概念
  • 创建一个新的基于Gradle的项目
  • 使用Gradle wrapper
  • 如何将Eclipse项目转化为Gradle项目

Android Studio

Android Studio于2013年5月发布(作为预览版本),同时支持Gradle。 Android Studio是基于JetBrains的IntelliJ IDEA开发,但是针对Android开发作了专门的功能定制。在Linux,Mac OS X和Microsoft Windows平台上均可免费下载,以下简称Android Studio为AS。

与Eclipse相比,Android Studio有如下有点:改进了用户界面编辑器;更好的内存监视器;不错的编辑器字符翻译;Android Lint警告和更多针对Android开发人员定制的功能。同时,除了IntelliJ IDEA中存在的常规Project视图和Packages视图外,AS还具有Android的特殊项目结构视图,此特殊视图将Gradle脚本,drawables和其他资源以方便的方式分组。在发布了稳定版本1.0的Android Studio后,Google不再维护Eclipse的Android开发人员工具(ADT),并建议所有开发人员切换到Android Studio。这意味着Google将不再为Eclipse提供新的功能,所有与IDE相关的工具开发现在都集中在Android Studio上。如果你仍然在使用Eclipse,是时候改变了。

更新AS

AndroidStudio有四个不同的更新渠道

  • Canary 此渠道是最新的更新,但是可能会产生bug
  • Dev 此渠道基于一个月更新一次
  • Beta 此渠道是用于新增功能全部完成后的版本,但是可能会产生bug
  • Stable 默认选项,新增功能经过测试后的稳定版本

默认情况下,AS会在每次启动时检查是否有可用的更新并会弹出更新通知框。当你首次启动Android Studio时,它会启动一个向导来设置您的环境,并确保你拥有最新的Android SDK和必要的Google Library。 AS还提供了创建Android虚拟设备(AVD)的选项,因此你可以在模拟器上运行应用程序。

了解Gradle基础知识

使用Gradle构建Android项目时,你需要设置一个构建脚本,脚本的名称通常规定为build.gradle。你会注意到,当我们在学习Gradle基础时,Gradle的很多语法都是约定俗称,并且通常会在配置文件中提供默认值。这使得我们在开始使用Gradle时,比使用Ant或Maven等构建系统更容易(Ant或Maven长期以来一直是Android项目构建系统)。

Gradle构建脚本不是用传统的XML编写的,而是基于Groovy的一种特定领域语言(DSL),它是Java虚拟机(JVM)的一种动态语言。 Gradle背后的团队相信,使用基于动态语言的声明式DSL风格方法比更多程序化,自由浮动的Ant或者许多其他构建系统使用的任何基于XML的方法相比具有显着的优势。

这并不意味着你需要先学习Groovy你才能开始写构建脚本。因为Groovy通俗易懂,如果你已经知道Java,学习曲线就更不是那么陡峭。如果你想创建自己的Gradle Task和Plugin(我们将在后面的章节中讨论),多学习Groovy有益于更深入的理解。另一方面,因为Groovy基于JVM,所以可以使用Java或任何其他基于JVM的语言编写自定义插件的代码。

项目和任务(Projects and tasks)

Gradle中有两个重要的概念:项目(Project)和任务(Task)。 Gradle Build至少由一个项目组成,并且每个项目包含一个或多个任务。 每个build.gradle文件都代表一个项目。 任务在build.gradle构建脚本中定义。 初始化构建过程时,Gradle基于构建文件组装Project和Task对象。 Task对象由Action对象的列表组成,按照它们需要执行的顺序。 Action对象是一个被执行的代码块,类似于Java中的方法。

构建过程的生命周期(The build lifecycle)

执行Gradle构建是最简单的形式,只是对依赖于其他任务的任务执行动作。 为了简化构建过程,构建工具将工作流的动态模型创建为定向非循环图(DAG)
这意味着所有的任务一个接一个地处理,循环执行是不可能的。 一旦任务被执行,它不会被再次调用。 没有依赖关系的任务将始终在其他任务之前运行。 依赖图在构建的配置阶段生成。 Gradle构建有三个阶段:

  • 初始化阶段(Initialization): 这个阶段Gradle会创建项目实例。 如果有多个模块,每个模块都会按照自己的build.gradle文件初始化,从而将创建多个项目。
  • 配置阶段(Configuration): 在此阶段,将执行构建脚本,为每个项目对象创建和配置所有任务。
  • 执行阶段(Execution): 这是Gradle确定应该执行哪些任务的阶段。 应该执行哪些任务取决于启动构建所传递的参数以及当前的运行目录。

Build配置文件

为了让Gradle构建一个项目,总是需要一个build.gradle文件。 Android的构建文件有几个必需元素:

1
2
3
4
5
6
7
8
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}

如上代码是实际构建配置的地方。在**repositories{…}**代码块中,将JCenter repository配置为构建脚本的依赖关系的源。 JCenter是一个Gradle预先内置的Maven存储库,Gradle默认已经配置好相关了,不需要你额外的设置 。 Gradle中还有几个内置的存储库,并且Gradle也支持添加自己的本地或远程仓库。

构建脚本**dependencies{…}**代码块中还定义了对Android build tools的依赖,这个依赖就是Android插件。 Android插件提供构建和测试应用程序所需的一切。 每个Android项目都需要应用Android插件,代码如下:

1
apply plugin: 'com.android.application'

插件用于扩展Gradle构建脚本的功能。 将插件应用于项目可以使你的构建脚本定义属性并使用插件中定义的任务。

如果你正在构建一个Library模块,那么在模块的build.gradle文件中你需要使用com.android.library而不是com.android.application。 同时你不能在一个模块中同时使用这两者,因为这将导致构建错误。 模块可以是Android Application或Android Library,但不能同时是两者。

在应用Android plugin之后,你就可以配置android构建相关的属性,Android插件定义了**android{…}**代码块,如下所示,你可以在你的项目build.grade文件中加入关于android的配置

1
2
3
4
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
}

上面的代码中,Android插件提供适合Android需求的DSL。 唯一需要的属性是compileSdkVersion和buildToolsVersion,由compileSdkVersion指定编译应用程序的SDK版本。 最好使用最新的Android API版本作为compileSdkVersion。

项目目录结构

与旧的Eclipse项目相比,Android项目的文件夹结构发生了很大的变化,如下图,这是Gradle应用程序的通用文件结构:

Gradle项目通常在Project根路径有一个额外的级别。 这使得以后更容易添加其他的模块。 应用程序的所有源代码都将进入app文件夹。 该文件夹也是模块的名称,默认情况下,不需一定命名成app。 例如,如果你使用Android Studio手机应用或者Android Wear智能手表应用的项目,默认情况下,分别命名成applicationwearable

Gradle有一个source set的概念。 官方Gradle文档描述了source set是一组一起编译和执行的源文件。对于Android项目,main目录是包含应用程序默认版本的所有源代码和资源的source set。 当你开始为Android应用程序编写测试时,你需要把测试的源代码放在一个名为androidTest的独立source set中,该source set仅包含测试代码。

以下是Android相关资源目录对应表:

目录 对应Android内容
/src/main/java 应用的源代码
/src/main/res 应用的资源代码layout,drawable,values等
/libs 引用的jar或者aar
/build 构建的输出内容,apk或测试报告等

使用Grade Wrapper

Gradle一直在更新,新版本可能会破坏向后兼容性。使用Gradle Wrapper是避免问题和确保构建稳定的好方法。

Gradle Wrapper在Windows平台上提供批处理文件,在其他操作系统上提供shell脚本。运行脚本时,如果Gradle指定版本不存在就会下载其所需的版本,然后自动用于构建。这意味着,每个开发人员或需要构建应用程序的自动化系统(例如CI)只用运行wrapper程序,wrapper将处理Gradle版本等兼容问题,而不需要在开发机上自己每次都手动安装正确版本的Gradle或构建服务器。因此,建议将wrapper文件添加到版本控制系统中(Git或SVN等)。

运行Gradle Wrappter与直接运行Gradle没有什么不同。你只需要在Linux和Mac OS X上执行gradlew,在Windows上执行gradlew.bat,而不是常规的gradle命令。

获取Gradle Wrapper

为了方便起见,每个新的Android项目默认都包括Gradle Wrapper,所以当你创建一个新的项目,你不必做任何事情。 当然,在你的计算机上手动安装Gradle并直接通过Gradle命令应用于你的项目也是可行的,但是这样就可能产生先前讨论的gradle兼容问题。Gradle Wrapper能执行Gradle所有的操作,并能使用正确的Gradle版本。所以,没有理由不使用wrapper在而使用单独Gradle工作。

你可以通过在终端中并进入项目根目录运行./gradlew -v或从windows cmd中运行gradlew.bat -v来检查项目中是否存在Gradle wrapper。运行此命令将显示Gradle的版本以及有关设置的一些额外信息。 如果项目是从Eclipse项目转化过来的,默认情况下不会安装wrapper。 在这种情况下,可以使用Gradle生成它,但是您需要先安装Gradle以获取wrapper。

Gradle下载页面有二进制文件和源代码的链接,如果你在Mac OS X上,可以使用包管理器,如Homebrew。所有的安装说明 在安装页面都有说明。

下载并安装Gradle并将其添加到PATH后,创建一个包含以下三行的build.gradle文件:

1
2
3
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
}

之后,运行gradle wrapper生成包装文件。在Gradle的最新版本中,你还可以运行wrapper任务而不修改build.gradle文件添加上面的代码,因为它默认已经作为任务包括在内。在这种情况下,可以直接使用–gradle-version参数指定版本,如下所示:

1
$ gradle wrapper --gradle-version 2.4

如果不指定版本号,则wrapper配置成使用执行任务的Gradle版本。
这些是wrapper任务生成的所有文件:

1
2
3
4
5
6
myapp/
|----gradlew
|----gradlew.bat
|----gradle/wrapper/
|----gradle-wrapper.jar
|----gradle-wrapper.properties

从上可知Gradle Wrapper有如下三部分:

  • 一个在Window平台下运行的批处理文件和在Linux/Mac OS X下运行的shell脚本
  • 一个JAR包,bat和shell会调用
  • 一个properties文件

gradle-wrapper.properties文件是包含配置的文件,并用力爱确定使用Gradle的什么版本,其内容大致如下:

1
2
3
4
5
6
#Sat May 30 17:41:49 CEST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip

如果要使用自定义的Gradle版本,可以更改distributionUrl。 这也意味着你使用的任何应用程序或库模块可能会有有不同的Gradle分发地址,因此在运行wrapper之前最好检查distributionUrl是否可以信任。

在项目中使用的Gradle版本不是最新版本时Android Studio会显示通知,并建议你自动为其更新。本质上,Android Studio意识更改gradle-wrapper中的distributionUrl配置属并触发重新构建,以便下载最新版本。

运行构建任务

在终端或命令提示符中,进入到项目根目录,并使用grade wrapper命令运行tasks:

1
$ gradlew tasks

这将打印出所有可用任务的列表。 如果添加–all参数,将获得每个任务的依赖关系等更详细的描述。

在Windows上,需要运行gradlew.bat,在Linux和Mac OS X上,完整命令为./gradle。 为了简洁,之后所有的相关命令都简写成gradlew

在开发调试Android项目时构建项目打包,需要运行assemble调试任务:

1
$ gradlew assembleDebug

此任务将生成一个调试版本的APK。默认情况下,Gradle的Android插件将APK保存在MyApp/app/build/outputs/apk目录中。

缩写的任务名称
为了避免在终端中进行大量输入,Gradle还提供了缩写的驼峰命名任务名称作为快捷方式。 例如,你可以通过从命令行界面运行gradlew assDeb或甚至gradlew aD来执行assembleDebug。
这里有一个注意事项。 只要骆驼情况缩写是唯一的,它就会正常运行,但是一旦另一个任务有相同的缩写,这个简写的名称就不起作用了。

除了assemble任务,还有其他三种类型的任务:

  • check任务:主要用错误检查,如运行单元测试或者UI集成测试
  • build任务:同时出发assemble和check任务
  • clean任务:清除构建过程中所有输出(outputs目录下)

从Eclipse迁移项目

从Eclipse项目迁移到基于Gradle的项目有两种方法:

  • 使用Android Studio中的导入向导自动处理迁移
  • 将Gradle脚本添加到Eclipse项目并手动设置所有内容

大多数项目都足够简单,AS导入向导能够自动转换一切。 如果有一些导入向导无法判断的东西,AS可以给你提示,然后你手动去修改。

然而,有些项目可能非常复杂,需要手动转换。 如果你有一个复杂庞大的项目,你喜欢逐步转换项目,而不是一次性转换,你可以执行Ant任务,甚至从Gradle中执行完整的Ant构建。 这样做,你可以按照你喜欢的速度进行转换,并慢慢转换所有的组件。

使用AS导入向导

要启动导入向导,你需要打开Android Studio,单击File菜单,然后单击Import Project…,或在Android Studio开始屏幕上,单击Import Non-Android Studio project

如果你的Eclipse项目中使用了JAR文件或其他Library,导入向导将建议用Gradle依赖项替换它们。 这些依赖关系可以来自本地Android SDK(例如Android Support包),甚至来自已知的在线repository。 如果未找到匹配的本地或线上依赖,则还是使用JAR文件,就像之前一样。 导入向导至少会为转换的项目创建一个模块。 如果你的项目中有源代码的Library库,那么这些库也将转换为模块。

导入向导提示如下所示:

转环视AS会创建一个新文件夹,以确保在转换时不丢失任何内容,你可以轻松地将导入向导的结果与原始文件进行比较。转换完成后,AS会打开该项目并显示一个导入摘要。

摘要列出导入向导决定忽略的并且未复制到新项目的所有文件。如果你任然要包括这些文件,你必须手动将它们复制到新项目。在忽略的文件下方,摘要显示导入向导能够替换为Gradle依赖项的所有JAR文件。AS会尝试在JCenter上找到这些依赖项。如果你使用Support包,它现在包含在Google Repository中,你需要通过SDK Manager下载到你的计算机的,而不是直接使用JAR文件。 最后,摘要列出导入向导已移动的所有文件,显示其来源和目标。

导入向导还会在项目根目录上添加三个Gradle文件:settings.gradlebuild.gradle,模块中添加另一个build.gradle,如果你有任何包含源代码的Library,导入向导也会将它们转换为Gradle项目,并根据需要将所有内容组合在一起。

该项目现在应该构建没有任何问题,但请记住,你可能需要在线连接下载一些必要的依赖项。

更复杂的项目可能需要额外的工作,所以接下来我们将看看如何手动进行转换。

Eclipse导出向导
Eclipse中还有一个导出向导,但它完全过时,因为Google Android的Android工具小组停止了Eclipse的Android开发工具。 因此,建议始终使用Android Studio中的导入向导。

手动转换

有多种方法可以手动迁移到基于Gradle的Android项目。 它不需要更改为新的目录结构,甚至可以从Gradle脚本运行Ant脚本。 这使迁移过程非常灵活,并且它可以使大型项目的转换更容易。

我们将在第9章“自定义高级构建”中查看运行的Ant任务。

保持老的项目结构

如果不想移动文件,可以在项目中保留Eclipse文件夹结构。为此,你需要更改source set的配置。我们在谈论项目结构时提到了source set。 Gradle和Android插件有他们的默认值,但是可以重写这些配置。

你需要做的第一件事是在项目目录中创建一个build.gradle文件。 此文件应该应用Android插件,并定义Gradle和Android插件所需的属性。 在其最简单的形式,它看起来应该是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
buildscript {
repositories {
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}

apply plugin: 'com.android.application'

android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
}

然后,你可以通过重写source set来符合Eclipse项目结构,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}

androidTest.setRoot('tests')
}
}

在Eclipse文件结构中,所有源文件都会驻留在同一个文件夹中,因此你需要告诉Gradle所有这些组件都可以在src文件夹中找到。因此,你只需要将项目中的组件都包括其中即可,同时,你也不必但系将所有都添加进去会带来什么坏的影响。

如果你对JAR文件有任何依赖关系,则需要告诉Gradle依赖所在的位置。假设JAR文件在一个名为libs的文件夹中,配置如下所示:

1
2
3
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}

上面代码的意思为将libs目录中的每个扩展名为.jar的文件都作为依赖。

转换为新的项目结构

如果你决定将项目手动转换为新的项目结构,则需要创建几个文件夹并移动一些文件。下表展示了一些最重要的文件和文件夹的概述,以及你需要将其移动到何处进行转换的新项目结构:

原位置 新位置
src/ app/src/main/java/
res/ app/src/main/res/
assets/ app/src/main/assets/
AndroidManifest.xml app/src/main/AndroidManifest.xml

如果你有任何单元测试,你需要将源代码移动到**app/src/test/java/下,让Gradle自动识别它们。 功能测试属于app/src/androidTest/java/**文件夹。

下一步是在项目的根目录中创建一个settings.gradle文件。 这个文件需要只包含一行,它的目的是告诉Gradle将应用程序模块包含在构建中:

1
include: ':app'

当如上的工作都准备好了,你还需要准备两个build.gradle文件,第一个属于项目的根目录(与settings.gradle在同一级别),用于定义项目范围的设置:

1
2
3
4
5
6
7
8
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
}

上面代码的作用主要是未项目中的所有模块设置了几个通用属性。第二个build.gradle放在app文件夹下,其内容为应用模块的相关设置:

1
2
3
4
5
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
}

以上这些配置都是基础的配置。如果你有一个不依赖第三方代码的简单Android应用程序,者就足够了。但是如果你项目中有任何第三方依赖,你就需要将它们迁移到Gradle依赖中。

转换Library项目

如果你的项目是供别人项目引用的第三方的Android Library,转换的步骤与以上大部分设置都相同,唯一不同的是,你需要使用Android Library插件,而不是Android Application插件。此过程的详细信息在第5章“管理多模块构建”中讨论。

总结

我们通过查看Gradle的优点以及为什么它比当前使用的其他构建系统更有用来开始本章。 我们简要地看了一下Android Studio,以及它如何帮助我们生成构建文件。

在介绍之后,我们看了一下Gradle Wrapper,这使维护和共享项目更容易。 我们在Android Studio中创建了一个新项目,现在您已经知道如何将Eclipse项目自动和手动迁移到Android Studio和Gradle。 您还能够在Android Studio中使用Gradle构建项目,或者直接从命令行界面构建项目。

在接下来的几章中,我们将讨论如何自定义构建,以便进一步自动化构建过程,并使维护更加轻松。 我们将首先检查所有标准Gradle文件,探索基本构建任务,并在下一章中定制构建的部分。