Android Gradle 基础

285 阅读16分钟

Android Gradle 是 Android 项目的构建工具,它基于 Gradle 构建系统,为 Android 应用的构建、测试、发布提供支持。Gradle 配置文件通常分为两个层级:项目级别的 build.gradle 文件模块级别的 build.gradle 文件

项目级 build.gradle:包含项目的全局配置。

模块级 build.gradle:针对特定模块(如 app 模块)进行配置。

接下来分别介绍这两个文件的作用、常用配置项,以及如何动态获取配置。


1. 项目级 build.gradle 文件

1.1 文件位置

项目级 build.gradle 文件位于项目根目录下,通常用于配置全局的插件和依赖、构建脚本仓库等。

1.2 常见配置

// 项目级别的 build.gradle 文件示例
buildscript {
    repositories {
        google() // 使用 Google's Maven 仓库
        mavenCentral() // 使用 Maven Central 仓库
    }
    dependencies {
        // Gradle 插件的依赖
        classpath 'com.android.tools.build:gradle:7.2.0' // Android Gradle 插件版本
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10' // Kotlin 插件版本
    }
}

allprojects {
    repositories {
	    // 各模块共享的仓库配置
        google() 
        mavenCentral()
    }
    dependencies {
        implementation 'com.android.support:appcompat-v7:28.0.0'
    }
}

subprojects {
    repositories {
        mavenCentral()
    }
}

plugins {
    id 'com.android.application' version '8.2.1' apply false
    id 'com.android.library' version '8.2.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir // 自定义清理任务,删除构建目录
}

1.3 配置项说明

1.3.1 buildscript:

用于配置构建脚本本身的特定部分。它的作用是定义 构建脚本的依赖项构建脚本所需的仓库,以及如何应用这些插件或依赖项。

buildscript 的作用:

  1. 定义构建脚本的依赖项(Classpath)

buildscript 主要用来定义构建脚本本身所依赖的类路径(classpath)。这意味着构建过程中所需要的插件或者工具的依赖是通过 buildscript 中的 dependencies 来声明的。例如,Android 项目通常会在这里声明 Android Gradle 插件(com.android.tools.build:gradle)和 Kotlin 插件(org.jetbrains.kotlin:kotlin-gradle-plugin)等。

  1. 定义仓库(Repositories)

repositories 作用是指定从哪里下载这些构建插件和依赖。通常会配置一些常用的仓库,如 google() 和 mavenCentral()。这些仓库包含了常见的插件和库。

  1. 为整个项目或子项目提供构建插件

buildscript 中配置的插件和依赖项通常会被用于构建项目,而不是在应用程序代码中使用。例如,Android Gradle 插件就在 buildscript 中声明,并且会影响整个项目的构建过程。

结构说明:

  • repositories 定义了构建过程中所需依赖的下载源。常用的仓库有:

    • google():适用于 Android Gradle 插件等 Android 相关依赖。
    • mavenCentral():适用于各种 Java 和 Kotlin 依赖。

必要性:

  • 插件管理:buildscript 使你能够指定构建过程所需要的插件和其版本,保证了构建环境中插件版本的统一性
  • 支持多模块构建:对于大型项目,可能会有多个模块(如应用模块、库模块等),buildscript 中的插件和依赖项会为所有这些模块提供共享的构建配置。
  • 构建环境的配置:通过 buildscript 配置,可以确保整个项目的构建过程使用的插件、工具和版本都是一致的,这有助于避免由于插件版本不一致导致的构建失败或异常。

1.3.2 allprojects:

用于配置 所有子项目(包括根项目和所有子模块)的构建设置。这些配置会应用到项目的所有子模块,允许在多个项目或模块之间共享。通常用于统一管理多个子项目的构建仓库、依赖项、插件等。

allprojects 的作用:

  1. 共享仓库配置

    allprojects 块通常用于为项目的所有子模块配置共享的仓库。这样,所有子模块都可以从相同的仓库中下载依赖项。你不需要在每个子模块的 build.gradle 文件中单独配置仓库。

  2. 共享插件和依赖配置

如果有多个子项目,并且希望它们使用相同的插件或依赖项,可以通过 allprojects 来统一配置。这使得管理依赖和插件变得更加高效。

  1. 统一配置设置

    除了仓库和依赖,allprojects 还可以用于设置其他共享的构建设置,例如版本号、代码风格、任务等。这种方式非常适用于大型多模块的项目,可以避免在每个子项目中重复配置。

  • repositories:定义了所有子项目(子模块)共享的仓库,确保每个模块都能访问到需要的依赖。

结构说明:

  • repositories:用于配置所有子项目共享的仓库。无需在多个子模块的 build.gradle 文件中重复声明仓库。比如配置了 google() 和 mavenCentral(),所有子项目都会使用这些仓库来查找和下载依赖。
  • dependencies:配置共享的依赖项。这些依赖项会被自动应用到所有子项目

必要性:

  • 统一的仓库配置:多模块项目统一配置所有模块使用相同的仓库,避免在每个模块中重复配置仓库。
  • 共享的依赖配置:为所有子项目统一配置共享的依赖,用于共享一些公共的库或插件
  • 统一的构建设置:用来统一所有模块的构建设置。例如,你可以配置所有模块的 Java 版本、Kotlin 编译选项等。
allprojects {
    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }

    tasks.withType(KotlinCompile) {
        kotlinOptions.jvmTarget = "1.8"
    }
}

1.3.3 subprojects

subprojects基本和allprojects一致,但是subprojects 只会影响子项目,而不会影响根项目:

  • allprojects:适用于根项目及其所有子项目。配置项会影响根项目和所有子项目。
  • subprojects:只会影响子项目(不包括根项目)。如果你有多个子模块,并且希望对子模块的构建配置进行统一管理,但不影响根项目,可以使用 subprojects。

如果你有多个子模块,并且希望对子模块的构建配置进行统一管理,但不影响根项目,可以使用 subprojects。

1.3.4 plugins

plugins 块用于声明和应用 Gradle 插件。这些插件扩展了 Gradle 构建系统的功能,允许使用特定的功能或任务,例如 Android 构建、Kotlin 编译、Java 编译等。使得管理插件的方式更加清晰简洁。

plugins的作用:

  1. 声明插件

    声明构建过程中要使用的插件,插件通过 ID 和版本号来标识。与 buildscript 中使用 classpath 声明插件不同,plugins 更简单。

  2. 应用插件

    插件是 Gradle 构建系统的核心扩展部分。通过 plugins 块,Gradle 会自动下载并应用所声明的插件,使得你可以使用该插件提供的任务、功能和配置。例如,Android 插件可以用来构建 Android 应用,Kotlin 插件可以用来编译 Kotlin 代码。

  3. 自动处理插件版本管理

    使用 plugins 块时,插件的版本号可以直接指定,Gradle 会自动从插件仓库下载对应的插件,而不需要手动设置插件依赖。这使得版本管理更加简洁,避免了手动管理插件版本的复杂性。

  4. 提高可读性和可维护性

    plugins 块声明插件的语法更直观和简洁,代码更加简洁、易懂,并且使得构建脚本的结构更清晰。

项目级的 Gradle 插件,一般用于全局配置。如插件定义、依赖管理等。可以跨多个子模块共享,减少了重复配置的需要。通过使用插件,Gradle 可以获得额外的功能。也能集中管理构建工具的版本,避免每个子项目都独立管理插件版本。

关键字段

  1. id:

    插件的唯一标识符。每个插件都必须有一个唯一的 id,通常这个 id 由插件的开发者指定。例如,com.android.application 用于 Android 应用构建插件,org.jetbrains.kotlin.android 用于 Kotlin 插件。

  2. version:

    插件的版本号。你可以指定插件的版本号,这样 Gradle 会确保使用指定版本的插件。例如,version '8.2.1' 表示使用该版本的插件。

  3. apply:

    指定插件是否被应用到项目中。apply false 用于在项目级 build.gradle 文件中声明插件,而实际应用插件的操作可能在子项目中进行,避免根项目直接应用插件。例如,apply false 表示插件不会自动应用到项目中,而是可以在子模块中按需使用。可以在模块级的 build.gradle 中选择性地启用插件。

必要性:

  • 语法更简洁:plugins 块的语法比传统的 buildscript 更简洁、直观。在 buildscript 中,你需要手动指定插件的类路径(classpath),而 plugins 块通过插件的 ID 和版本号来声明插件,Gradle 会自动管理依赖。
  • 更易于维护:不需要手动添加 classpath 依赖并管理插件版本,Gradle 会自动处理。
  • 减少冲突:通过指定插件的版本号,可以确保不同的模块或子项目使用一致的插件版本,避免了版本冲突的问题。
  • 减少重复配置:支持在多个模块中应用同样的插件,通过声明并共享插件配置,减少了重复代码。

plugins 与 buildscript 的区别:

  • plugins :是一个简洁的插件声明方式,通常用于声明和应用插件。它会自动从插件仓库下载插件并进行版本管理。
  • buildscript :通常用于声明插件的类路径(classpath),适用于需要自定义插件或插件类路径的情况。

1.3.5 task clean

  • 自定义 Gradle 任务,删除构建目录,通常用于清理构建结果。在该示例中,其作用如下:

    • task clean:这是一个自定义任务,用于删除构建目录 build。通常在执行 ./gradlew clean 命令时,Gradle 会调用这个任务来清理生成的构建文件。
    • type: Delete:指定该任务的类型是 Delete,表示删除文件或目录。
    • delete rootProject.buildDir:表示删除根项目的构建目录,即 rootProject/build。

1.4 动态获取配置的方式

ext {
    // 定义一个全局的版本号
    kotlin_version = '1.6.10'
}

// 在子项目中引用
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

通过 ext 属性可以定义全局变量,然后在各模块中引用这些变量。


2. 模块级 build.gradle 文件

2.1 文件位置

每个 Android 模块(如 app)都有自己的 build.gradle 文件,用于配置该模块的构建选项和依赖。

2.2 常见配置

// 模块级别的 build.gradle 文件示例
plugins {
    id 'com.android.application' // Android 应用插件
    id 'org.jetbrains.kotlin.android' // Kotlin 插件
}

android {
    compileSdkVersion 34 // 编译 SDK 版本

    defaultConfig {
        applicationId "com.example.myapp" // 应用 ID
        minSdkVersion 21 // 最小支持 SDK 版本
        targetSdkVersion 34 // 目标 SDK 版本
        versionCode 1 // 版本号
        versionName "1.0" // 版本名称
    }

    buildTypes {
        release {
            minifyEnabled true // 启用代码混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // 配置 ProGuard
        }
        debug {
            minifyEnabled false // 调试版本禁用混淆
        }
    }

    productFlavors {
        free {
            applicationIdSuffix ".free" // 应用 ID 后缀
        }
        paid {
            applicationIdSuffix ".paid" // 应用 ID 后缀
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17 // 设置 Java 编译版本
        targetCompatibility JavaVersion.VERSION_17
    }

    buildFeatures {
        viewBinding true // 启用 ViewBinding
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.4.1' // AppCompat 库
    implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.6.10' // Kotlin 库
    testImplementation 'junit:junit:4.13.2' // JUnit 测试库
}

2.3 配置项说明

2.3.1 plugins

声明并应用 Gradle 插件。通过插件启用构建特性或任务。例如,com.android.application 用于构建 Android 应用,org.jetbrains.kotlin.android 用于在 Android 项目中使用 Kotlin。

plugins 既可以在项目级的 build.gradle 文件中配置,也可以在模块级的 build.gradle 文件中配置。虽然它们的配置方式有所不同,但主要的区别在于作用范围和功能。

其和根目录下项目级的plugins的区别如下:

1. 项目级 plugins

  • 作用范围:在项目级的 build.gradle 中配置的插件,通常用于定义整个项目的构建逻辑,或者应用于所有模块(子项目)中。

  • 作用:项目级插件配置主要用来为所有子模块提供构建工具、插件或库的版本管理。这些插件通常是全局插件,确保整个项目或所有模块使用相同的构建配置、版本等。

  • 常见用法:配置用于构建 Android 项目所需的插件、Kotlin 插件等。

  • 项目级插件的一些常见功能:

    • 插件版本管理:你可以在项目级别声明插件的版本,避免在每个模块中重复配置插件版本。
    • 全局插件配置:例如,Android 和 Kotlin 插件通常需要在项目级别声明。

2. 模块级 plugins

  • 作用范围:在模块级的 build.gradle 中配置的插件,作用仅限于该模块。每个模块的 build.gradle 文件通常会指定与该模块相关的插件。

  • 作用:模块级插件用于具体化某个模块的构建逻辑。例如,如果某个模块是 Android 应用模块,则可以在该模块的 build.gradle 文件中启用 com.android.application 插件。如果是库模块,则启用 com.android.library 插件。

  • 常见用法:在各个模块中配置 Android 插件、Kotlin 插件,或其他库插件等。

  • 模块级插件的一些常见功能:

    • Android 构建插件:根据模块的性质,使用 com.android.application 或 com.android.library 插件来构建 Android 应用或库。
    • Kotlin 插件:启用 Kotlin 支持并为模块提供编译和其他 Kotlin 特性。

3. 区别总结

项 目项目级 plugins 配置模块级 plugins 配置
作用范围整个项目(包括所有子模块)仅限于当前模块(子模块)
配置方式通常在项目根目录的 build.gradle 文件中配置每个模块的 build.gradle 文件中配置
插件类型一般为全局性插件,例如 Android、Kotlin 等与模块构建相关的插件,例如 com.android.applicationcom.android.library
常见用途管理插件版本、全局配置插件针对每个模块的具体构建任务,如构建 Android 应用或库

4. 插件的应用

  • 项目级插件配置:主要目的是统一插件版本,确保所有模块使用相同的版本。例如,Android Gradle 插件和 Kotlin 插件的版本需要在项目级别一致。
  • 模块级插件配置:在模块级的 build.gradle 中,针对不同的模块选择相应的插件并应用。例如,一个模块可能是 Android 应用模块 (com.android.application),另一个模块可能是 Android 库模块 (com.android.library)。

2.3.2 android 配置

  • compileSdkVersion:指定应用编译时使用的 Android SDK 版本。

  • defaultConfig:模块的基本配置,包括应用 ID、最小 SDK 版本、目标 SDK 版本、版本号等。

    常用字段

    • applicationId:应用的唯一标识符。
    • minSdk:最低支持的 Android SDK 版本。
    • targetSdk:应用优化支持的目标 SDK 版本。
    • versionCode:版本号,唯一且递增,用于标识不同版本的应用。
    • versionName:版本名称,通常是用户可见的版本号(如 1.0)。
  • buildTypes:配置不同的构建类型,如 debug 和 release。每个构建类型可以有不同的设置,如是否混淆代码、是否启用调试信息等。

    常用字段

    • isMinifyEnabled:是否启用代码压缩和混淆。true 表示启用混淆,false 表示不启用。
    • proguardFiles:指定混淆配置文件,getDefaultProguardFile 获取默认的 ProGuard 配置,通常用于 release 构建类型。
  • productFlavors:定义产品类别,可以用来区分不同的产品版本(如 free 和 paid,或者 mobile 和 pad),用于创建不同版本的应用。

    常用字段:

    • applicationIdSuffix:应用 ID 后缀,不同的类型可以有不同的应用 ID
    • versionNameSuffix:版本名称后缀,用于区分不同版本。
  • compileOptions:用于配置 Java 编译选项,确保项目兼容性和提升构建性能。

  • buildFeatures:用于启用或禁用 Android 构建系统中的某些特性的一部分。它允许开发者开启或关闭一些构建功能,比如 ViewBinding、DataBinding、Jetpack Compose 等。这些功能帮助简化开发过程,提升开发效率,并且提高项目的可维护性。

    配置项

    • viewBinding:启用或禁用 ViewBinding,它是一种自动生成视图绑定类的功能,可以避免 findViewById 操作,简化代码,提升开发效率。默认情况下,viewBinding 是禁用的。

    • dataBinding:启用或禁用 DataBinding,允许将 UI 元素和数据对象绑定在一起,简化 UI 更新的代码。

    • compose: 启用或禁用 Jetpack Compose,这是 Android 的声明式 UI 框架,用于更简洁地构建用户界面。

    • buildConfig:启用或禁用 BuildConfig 文件的自动生成。它允许在构建时生成一些常用的构建常量(如版本号、构建类型等)。

    • customBuildFeatures:一些特定于插件的功能,允许你开启或关闭其他的构建功能。

      示例:

android {
    compileSdkVersion 34

    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 21
        targetSdkVersion 34
    }

    buildFeatures {
        viewBinding = true        // 启用 ViewBinding
        dataBinding = false       // 禁用 DataBinding
        compose = true            // 启用 Jetpack Compose
        buildConfig = true        // 启用 BuildConfig
    }
}
  • dependencies:用于声明项目所依赖的外部库或模块。它指定了哪些依赖项需要在构建过程中被包括到 APK 或 AAB 中。通过声明这些依赖项,Gradle 会自动下载、编译并将其打包到项目中 常用配置:

    • implementation:它表示库或模块是项目的实现依赖(即运行时和编译时都需要),引入的库不会传递给其他模块,意味着它们不会作为依赖暴露给依赖此项目的其他模块。
    • api:通常用于库模块。当库模块依赖其他库时,这些库会暴露给依赖该库的其他模块,它们会成为公共的依赖。
    • compileOnly:表示只在编译时需要,但不会包含在最终的 APK 中,适用于那些只在编译时需要存在的库(例如编译器插件或注解处理器)。
    • runtimeOnly:表示只在运行时需要的库,不会在编译时提供。适用于运行时才需要的库,例如数据库驱动程序等。
    • testImplementation:声明仅在测试代码中使用的依赖。它只影响测试构建过程,不会包含在主应用程序的构建中。适用于测试库、测试框架等。
    • androidTestImplementation:声明仅在 Android 测试代码中使用的依赖。它只影响 Android 单元测试和 UI 测试。适用于 Android 测试框架。
    • kapt:kapt 是 Kotlin 的注解处理工具(Kotlin Annotation Processing Tool)。它用来处理需要编译时注解的库或模块。适用于使用注解处理器的库。
    • 动态获取依赖版本,通常使用版本范围来指定依赖项。例如:
    dependencies {
        implementation 'com.squareup.okhttp3:okhttp:4.+'
    }
    

2.4 动态获取配置的方式

  • 获取环境变量

    可以通过 Gradle 内置的 project 对象获取动态配置。例如,从外部文件或环境变量获取版本号。

def versionCode = project.hasProperty('versionCode') ? project.versionCode : 1

defaultConfig {
    versionCode versionCode
}
  • 动态加载属性文件

    使用 Properties 类动态加载版本号或其他配置。

def properties = new Properties()
file("local.properties").withInputStream { stream ->
    properties.load(stream)
}

defaultConfig {
    versionCode properties['versionCode'].toInteger()
    versionName properties['versionName']
}
  • gradle.properties 文件中定义全局属性

    可以在 gradle.properties 文件中定义配置,并在 build.gradle 文件中引用。

# gradle.properties
VERSION_CODE=1
VERSION_NAME=1.0

然后在 build.gradle 中引用:

defaultConfig {
    versionCode project.VERSION_CODE
    versionName project.VERSION_NAME
}

总结

  • 项目级 build.gradle:

    • 用于配置全局构建环境,主要包括插件依赖、仓库配置、构建脚本的版本等。
    • 动态获取配置信息可以通过 ext 定义全局变量,并在模块级别的 build.gradle 中引用。
  • 模块级 build.gradle:

    • 用于配置特定模块(如 app)的编译和构建选项,包含构建类型(buildTypes)、产品类型(productFlavors)、依赖关系等。
    • 可以通过动态获取配置(如从 gradle.properties 或外部文件中加载)来实现灵活的构建。