51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Android开发中Gradle配置的相关概念介绍

引言 {#引言}

Gradle是一个项目构建工具,类似Maven,可用于管理项目内部组件的依赖关系,完成自动化构建。因为Android Studio生成的Android项目默认使用gradle进行构建,因此大多数Android程序员都要跟它打交道,今天这篇文章主要想厘清Android开发中与gradle相关的一些简单但是很基础的概念。

项目自动化构建 {#项目自动化构建}

首先想一下我们为什么需要项目的自动化构建工具,一般的开发中我们点一下Run/Debug按钮等一会apk就自动装到手机上去了,但实际上发生了很多我们看不到的事:

  • xml文件被编译成二进制文件,aidl文件编译成java,一些编译时的java代码被生成(如R文件)
  • java代码被编译成*.class字节码,最后编译成dex文件
  • 代码文件和资源文件放到一起被打包
  • 使用密钥进行安装包的签名,然后进行字节对齐的优化

以上是大致过程(细节或许有出入),其中每个过程还可以配置详细的参数(比如资源编译处理时的进程数、class编译到dex过程中进程数量、堆大小等等),如果这些小步骤都要程序员一步步去做就太繁琐了(可以看看这篇文章:手动命令行编译APK)。我们可以写一个脚本自动化地去做这些事(也就是说不用gradle这类的工具也是可以的),但是一个项目也许会引用到几十上百个库、模块之间存在复杂的依赖关系,而且项目构建还涉及到清理(clean)、测试、模块发布等环节,因此使用自动化构建工具就会方便很多。

Gradle与Wrapper {#Gradle与Wrapper}

Gradle可以直接去官网下载安装,但一般没这个必要,因为Android Studio会自带一个Gradle,就在Android Studio的安装目录下。同时Gradle也支持我们在没有安装 Gradle 的机器上运行 Gradle 构建,方法就是使用Gradle wrapper。这里的Gradle wrapper可以理解为一个绿色版的便携的gradle。

在Android开发中,一个团队内可能每个人机器上的gradle版本是不一样的,版本不一样可能导致构建出现问题,因此Android Studio对于项目默认是使用gradle wrapper的,而不是使用本地gradle。每个项目根目录下的gradle目录内都有一个gradle-wrapper.properties文件,里面规定了这个项目使用的gradle版本。一般Android Studio打开加载一个新的项目时会根据这个文件的内容去下载相应版本的gradle wrapper,当然如果本地已经有了这个版本的gradle wrapper就不用下载了。对于Windows系统,下载的wrapper一般在C:/用户目录/.gradle/wrapper/dists下。

假设gradle-wrapper.properties的内容如下:

|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | #Mon Dec 28 10:00:20 PST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip |

则说明将会去下载2.14.1的gradle wrapper,一般我们打开一个github上下载下来的项目,很容易卡死在这个环节(因为gradle.org服务器在国外,网速慢)。一般有多种解决办法:

  • 从国内站点下一个wrapper,这样网速快很多,然后拷到本地的"C:/用户目录/.gradle/wrapper/dists"下,注意命名一致。
  • 修改gradle-wrapper.properties里的版本号,找一下本地有哪些下好的版本,直接修改成这个版本,但是我是不推荐这么做,因为替换成不同版本的gradle wrapper可能导致构建失败,因为不同版本的特性可能不一样,如果只是下一个demo看看则无所谓,如果是团队协作应保证版本的一致。

基本概念 {#基本概念}

在Gradle中,比较重要的两个概念就是projectstasks。每一个构建都是由一个或多个 projects 构成的,每一个 project 是由一个或多个 tasks 构成的,一个 task 代表一些更加细化的构建, 可能是编译一些 classes, 创建一个 JAR, 生成 javadoc, 或者生成某个目录的压缩文件。

每一次Android Studio为我们自动生成的项目里的build.gradle文件里,我们可以找到:

|---------------|------------------------------------------------------------------| | 1 2 3 | task clean(type: Delete) { delete rootProject.buildDir } |

这里就定义了叫做cleantask,我们可以在命令行里使用命令gradlew tasks来查看当前目录下的build.gradle文件里的tasks列表。我对一个新建的空项目使用了这个命令,得到如下信息:

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | :tasks ------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------ Android tasks ------------- androidDependencies - Displays the Android dependencies of the project. signingReport - Displays the signing info for each variant. sourceSets - Prints out all the source sets defined in this project. Build tasks ----------- assemble - Assembles all variants of all applications and secondary packages. assembleAndroidTest - Assembles all the Test applications. assembleDebug - Assembles all Debug builds. assembleRelease - Assembles all Release builds. build - Assembles and tests this project. buildDependents - Assembles and tests this project and all projects that depend on it. buildNeeded - Assembles and tests this project and all projects it depends on. clean - Deletes the build directory. compileDebugAndroidTestSources compileDebugSources compileDebugUnitTestSources compileReleaseSources compileReleaseUnitTestSources mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests. Build Setup tasks ----------------- init - Initializes a new Gradle build. [incubating] wrapper - Generates Gradle wrapper files. [incubating] Help tasks ---------- buildEnvironment - Displays all buildscript dependencies declared in root project 'Demo'. components - Displays the components produced by root project 'Demo'. [incubating] dependencies - Displays all dependencies declared in root project 'Demo'. dependencyInsight - Displays the insight into a specific dependency in root project 'Demo'. help - Displays a help message. model - Displays the configuration model of root project 'Demo'. [incubating] projects - Displays the sub-projects of root project 'Demo'. properties - Displays the properties of root project 'Demo'. tasks - Displays the tasks runnable from root project 'Demo' (some of the displayed tasks may belong to subprojects). Install tasks ------------- installDebug - Installs the Debug build. installDebugAndroidTest - Installs the android (on device) tests for the Debug build. uninstallAll - Uninstall all applications. uninstallDebug - Uninstalls the Debug build. uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build. uninstallRelease - Uninstalls the Release build. Verification tasks ------------------ check - Runs all checks. connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices. connectedCheck - Runs all device checks on currently connected devices. connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices. deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers. deviceCheck - Runs all device checks using Device Providers and Test Servers. lint - Runs lint on all variants. lintDebug - Runs lint on the Debug build. lintRelease - Runs lint on the Release build. test - Run unit tests for all variants. testDebugUnitTest - Run unit tests for the debug build. testReleaseUnitTest - Run unit tests for the release build. Other tasks ----------- clean extractProguardFiles jarDebugClasses jarReleaseClasses transformResourcesWithMergeJavaResForDebugUnitTest transformResourcesWithMergeJavaResForReleaseUnitTest To see all tasks and more detail, run gradlew tasks --all To see more detail about a task, run gradlew help --task <task> BUILD SUCCESSFUL Total time: 14.137 secs |

可以看到名为cleantask已经在Other Task分类下。让gradle执行一个task的命令是"gradle 任务名",在Android Studio的命令行下也可以用"gradlew 任务名"(gradlew是gradle wrapper的意思)。因此对于上面列出的task清单,可以分别去跑这些task,如:

|---------------|--------------------------------------------------| | 1 2 3 | gradlew init gradlew build gradlew clean |

这些task具体是干什么的就不做深究了。另外gradle/gradlew命令后面可以跟参数:比如加-q就是静默构建,不显示任何log信息,加--info就是显示info级别的log信息,加--debug就是显示debug级别的log信息。

Gradle 默认在 src/main/java 目录下查找项目源代码, 在 src/test/java 目录下查找测试代码, 因此Android Studio生成的项目的目录结构是跟gradle有关系的。(在Eclipse上开发的Android项目的目录就跟AS生成的不一样)

Gradle使用groovy语言来描述构建脚本,groovy语言跟Java比较像。这里不多介绍了。

Android Plugin {#Android-Plugin}

Gradle最早的版本在2007年发布,而Android手机2008年才出现,Gradle其实跟Android开发本来是没有什么关系的,直到Google开始推Android Studio后Gradle才在Android开发中慢慢使用开来。

Google推出了Android Gradle Plugin,以便在Android项目中使用gradle进行自动化构建。Android Studio生成的build.gradle自动引入了Android Gradle Plugin,在项目根目录的build.gradle中可以看到:

|---------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 | buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } |

这里的2.2.3就是Android Plugin的版本号。如果我们要使用别的gradle插件(如android-apt),就要在这里的dependencies里添加相应的类路径(classpath),否则就可能报找不到插件之类的错误。
Google开发的Gradle插件有3种:

  • com.android.application
  • com.android.library
  • com.android.test

字面上就可以看出,分别是用于应用、库和测试模块的。应用这些插件的代码在项目的子模块下的build.gradle文件里:

|-----------|-------------------------------------------------| | 1 | apply plugin: 'com.android.application' |

一般在引入插件后,下面就两个代码块:

|------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | android { compileSdkVersion xx buildToolsVersion "xxx" defaultConfig { xxx } buildTypes { xxx } } dependencies { xxx } |

一般就是android{}dependencies{}。其中android代码块里面的各种配置全部源自于com.android.xxx 这个插件内,我们可以通过阅读官方文档进行相关参数的配置。而dependencies代码块内一般是对项目所需要各种库的描述。我们都知道,在GitHub上找到了一个合适的库,只要Maven仓库里有,就可以直接用一句 "compile xxx.xxx:abc:x.y.z" 代码就可以引入到项目里,项目构建时就会自动下载并添加到依赖项里。

相关配置 {#相关配置}

根据官方文档,android{}内有以下选项可以配置:

|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | aaptOptions { } adbOptions { } buildTypes { } compileOptions { } dataBinding { } defaultConfig { } dexOptions { } externalNativeBuild { } jacoco { } lintOptions { } packagingOptions { } productFlavors { } signingConfigs { } sourceSets { } splits { } testOptions { } |

但不是每个选项都会经常用到。经常用到的可能有:

  • signingConfigs{} 用于配置签名信息
  • splits{} 可以根据dpi、abi进行分包
  • productFlavors {} 多渠道打包
  • dexOptions{} 加速编译
    groovy语言可以使配置能加灵活和强大,不过我还在学习中,没法展开了。

参考文档 {#参考文档}

Gradle User Guide的中文翻译
android plugin的参考文档
Android项目构建官方文档

参考链接:https://www.jianshu.com/p/a54a49424f7a


赞(4)
未经允许不得转载:工具盒子 » Android开发中Gradle配置的相关概念介绍