这个系列的文章是自学笔记来源于《Gradle for Android》一书
如果你想用Gradle构建你的Android项目,那么你需要创建一个构建脚本,这个脚本通常被叫做build.gradle,Gradle构建脚本的书写没有基于传统的XML文件,而是基于Groovy的领域专用语言(DSL),但是这并不意味着在我们开始学习构建脚本之前需要学习Groovy,但是如果你想创建自己的任务和插件,那么对Groovy有更深层次的理解就显得尤为重要,然而Groovy是一种基于Java虚拟机的动态语言,所以你完全可以用Java或者其他基于Java虚拟机的语言来编写你的自定义插件。
理解Gradle文件
当我们创建一个新的项目时,会看到这三个文件
这三个文件都是做什么用的呢?
settings.gradle
打开默认是这样的
settings.gradle文件在初始化阶段被执行,并且定义了哪些模块应该被包含在构建内,在上图中,app模块被包含在内。
顶层构建文件(根目录下的build.gradle)
buildscript {
ext.kotlin_version = '1.1.51'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
我们看下buildscript和allprojects这两个代码块的内容
buildscript中的声明是gradle脚本自身需要使用的资源。可以声明的资源包括依赖项、第三方插件、maven仓库地址等。
而在build.gradle文件中直接声明的依赖项、仓库地址等信息是项目自身需要的资源。
虽然gradle支持开箱即用,但是如果你想在脚本中使用一些第三方的插件、类库等,就需要自己手动添加对这些插件、类库的引用。而这些插件、类库又不是直接服务于项目的,而仅仅是支持它build脚本的运行。所以你应当将这部分的引用放置在buildscript代码块中。gradle在执行脚本时,会优先执行buildscript代码块中的内容,然后才会执行剩余的build脚本。
buildscript代码块中的repositories和dependencies的使用方式与直接在build.gradle文件中的使用方式几乎完全一样。唯一不同之处是在buildscript代码块中你可以对dependencies使用classpath声明。该classpath声明说明了在执行其余的build脚本时,class loader可以使用这些你提供的依赖项。这也正是我们使用buildscript代码块的目的。
allprojects代码块用来声明那些需要被用于所有模块的属性,你甚至可以在allprojects中创建任务,这些任务最终会被运用到所有模块
app模块下的构建文件build.gradle
app模块的build.gradle文件的属性只能应用到app模块,它可以覆盖顶层build.gradle文件的任何属性
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.huozhenpeng.myapplication"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
这里面大致分为三个部分,插件、Android模块、依赖模块
插件
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
这三行代码就是插件,这些插件在顶层构建文件中都有被依赖,就是这些
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
android
在构建文件中,占比最大的就是android代码块,该代码块包含了全部的、Android特有的配置,这些特有配置之所以可以被使用,是因为之前我们使用了Android插件
compileSdkVersion 是用来编译应用的Android API版本
buildToolsVersion 是构建工具和编译器使用的版本
构建工具中包含的命令行应用,如aapt、dx、zipalign等都被用来在打包应用时生成各种中间产物,defaultConfig代码块用于配置应用的核心属性,defaultConfig代码块中的属性可以覆盖AndroidManifest.xml文件中对应的属性
defaultConfig {
applicationId "com.example.huozhenpeng.myapplication"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
applicationId覆盖了AndroidManifest.xml中的package属性,在Gradle被用作默认的Android构建系统之前,AndroidManifest.xml中的package属性有两个用途:1作为一个应用的唯一标志 ,2在R资源类中被用作包名。使用构建variants,Gradle可以更容易地创建不同版本的应用,例如,构建variants可以很容易地构建一个免费版和一个付费版应用,这两个版本需要有独立的标识符才能在Google Play Store中以不用的应用出现,并且可以同时被安装,然而资源代码和生成的R类必须在任何时候都保持相同的包名,否则你的源文件都要随着你正在构建的版本二发生改变,所以这就是Android工具团队解耦了package这两种不同方式的原因,定义在AndroidManifest.xml中的package继续用在源代码和R类中,而被用作设备和Google Play唯一标识的则用applicationId代替。
minSdkVersion用来配置运行应用的最小API级别
targetSdkVersion用于通知系统,该应用已经在某个特定Android版本通过测试,操作系统不必启用任何向前兼容的行为
构建文件中的属性会全面覆盖AndroidManifest.xml中的属性,因此,如果你在build.gradle中定义了它们的话就没有必要在AndroidManifest.xml中再去定义,如果构建文件中没有包含这个属性,AndroidManifest.xml中的属性才会起作用
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildTypes代码块用来定义如何构建和打包不同构建类型的应用。
依赖模块
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
依赖模块是标准Gradle配置的一部分,这也是它为什么放在android代码块之外的原因,它定义了一个应用或依赖项目的所有依赖包。