什么是Gradle?

Gradle 是一个开源的构建自动化系统。它拥有基于 Groovy 的 DSL 的便利以及 Ant 和 Maven 的优势。
使用 Gradle,您可以轻松地操纵构建过程及其逻辑,以创建应用程序的多个版本。与单独使用 Ant 或 Maven 相比,它更易于使用,更加简洁和灵活。 

入门

新建一个 Android project,将以该项目进行讲解。

在开始处理项目之前,让我们在 Android Studio 的 "project" 选项中查看其结构:

Android hilt 和 gradle 对应版本 android gradle是什么_android

注意带有绿色 Gradle 图标和扩展名 .gradle 的文件。这些文件由Android Studio在项目创建过程中自动生成。他们负责处理项目的构建。它们包含有关项目结构,库依赖项,库版本以及在构建过程中将获得的应用程序版本的必要信息。 

Project 层的 build.gradle

在项目的根目录中找到 build.gradle 文件。它称为顶级(项目级别)build.gradle 文件。它包含适用于项目所有模块的设置。

// 1
buildscript {
    // 2
    repositories {
        google()
        jcenter()
    }
    // 3
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.51'
    }
}

// 4
allprojects {
    repositories {
        google()
        jcenter()
    }
}

这是逐步进行的操作:

  • buildscript
  • repositories 块中,添加 Gradle 应搜索使用的库的存储库名称。
  • dependencies 块包含必要的插件依赖性,在这种情况下为 Gradle 和 Kotlin 插件。不要将模块依赖项放在此块中。
  • allprojects

Moudle 层的 build.gradle

现在转到应用程序模块目录中的build.gradle文件。它包含依赖项(模块所依赖的库)以及构建过程的说明。每个模块定义其自己的build.gradle文件。

// 1
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

// 2
android {
    // 3
    compileSdkVersion 27
    // 4
    buildToolsVersion "26.0.2"
    // 5
    defaultConfig {
        // 6
        applicationId "com.raywenderlich.socializify"
        // 7
        minSdkVersion 21
        // 8
        targetSdkVersion 27
        // 9
        versionCode 1
        // 10
        versionName "1.0"
    }
}

// 11
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.51'
    implementation 'com.android.support:appcompat-v7:27.0.1'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}

上面的代码执行以下操作:

  1. 指定构建模块所需的插件列表。该 com.android.application
  2. 在该 android
  3. 该 compileSdkVersion
  4. 该 buildToolsVersion
  5. 该 defaultConfig
  6. 该 applicationId
  7. 为了设置支持的最低API级别,请使用 minSdkVersion。在 API 级别较低的设备上,您的应用将无法在 Google Play 商店中使用。
  8. 该 targetSdkVersion
  9. versionCode
  10. versionName
  11. 该 dependencies

settings.gradle

根目录中的 settings.gradle 文件。其内容应如下所示:

include ':app'

在此文件中,应按名称定义项目的所有模块。在这里,我们只有一个模块 — app。在大型,多模块的项目中,此文件会有更长的列表。

Gradle 命令

要执行Gradle命令,您可以同时使用命令行和 Android Studio。最好从命令行开始,以更深入地了解正在发生的事情。那么,如何开始使用 Gradle 命令呢?非常简单:使用 gradlew。

什么是 gradlew

gradlew 是 Gradle 包装器。您无需担心在计算机上安装 Gradle,包装程序将为您完成此操作。甚至更多,它使您可以使用不同版本的 Gradle 构建不同的项目。

打开命令行并移至入该项目的根目录,之后,执行以下命令:

./gradlew tasks

您将看到一个包含所有可用任务的列表:

> Task :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 Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
...

Install tasks
-------------
...

Verification tasks
------------------
...
lint - Runs lint on all variants.
...

To see all tasks, run gradlew tasks --all

To get more detail about task, run gradlew help --task <task>

这些命令可以帮助您完成项目初始化,构建,测试和分析等任务。如果您忘记了一个特定的命令,只需执行 ./gradlew tasks

gradlew assemble

现在,再次浏览命令列表,并在该部分下找到以 “assemble” 开头的命令 Build tasks。运行第一个命令:

./gradlew assemble

 

以下是执行此命令的输出

> Task :app:compileDebugKotlin
Using kotlin incremental compilation

> Task :app:compileReleaseKotlin
Using kotlin incremental compilation


BUILD SUCCESSFUL in 29s
52 actionable tasks: 52 executed

从输出中,这是显而易见的是摇篮的编译应用程序的两个版本 - debug 和 release。
通过更改到构建输出目录来验证此内容:

cd app/build/outputs/apk/

要查看目录的内容,请运行以下命令:

ls -R

该 ls 命令显示当前目录中的所有文件和目录。该 -R 参数强制此命令以递归方式执行。换句话说,您不仅会看到当前目录的内容,还会看到子目录的内容。

您将获得以下输出:

debug    release

./debug:
app-debug.apk    output.json

./release:
app-release-unsigned.apk    output.json

如您所见,Gradle 生成了 debug 和 release apk。

管理依赖关系 

现在是时候对应用程序本身进行更改了。

首先,在项目的根目录中创建一个名为 dependencies.gradle 的文件。您将使用此文件在一处识别所有项目依赖项版本。将以下内容添加到此文件:

ext {
  minSdkVersion = 17
  targetSdkVersion = 27
  compileSdkVersion = 27
  buildToolsVersion = “ 26.0.2” 
  kotlinVersion = “ 1.1.51 ” 
  supportVersion = “ 27.0.1” 
  picassoVersion = “ 2.5.2”
}

打开项目级别的 build.gradle 文件(位于根目录中的一个,而不是 app 目录中的一个!),然后在文件顶部添加以下行:

apply from: 'dependencies.gradle'

现在,您可以像下面这样使用其他项目构建文件中在 dependencies.gradle 文件中指定的属性:

应用程序模块级别的 build.gradle

android {
    compileSdkVersion rootProject.compileSdkVersion
    buildToolsVersion rootProject.buildToolsVersion
    defaultConfig {
        applicationId "com.raywenderlich.socializify"
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "com.android.support:appcompat-v7:$rootProject.supportVersion"
    implementation "com.android.support:design:$rootProject.supportVersion"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.kotlinVersion"
}

Gradle依赖项配置

implementation 您先前使用的关键字是依赖项配置,该配置告诉 Gradle 以这种方式添加依赖,其他模块无法使用它。该选项大大加快了构建时间。

在某些其他情况下,您可能希望项目的其他模块可以访问依赖项。在这种情况下,您可以使用 api 关键字。

其他选项包括 runtimeOnly 和 compileOnly 配置,它们仅在运行时或编译时标记依赖项的可用性。

准备发布:使用 Product Flavors and Build Types

您的应用已准备就绪,您正在考虑怎么从项目中获利的方法:

Android hilt 和 gradle 对应版本 android gradle是什么_Gradle_02

一种解决方案是拥有多个版本的应用程序:免费和付费版本。幸运的是,gradle 在构建级别支持此功能,使您可以定义不同构建类型的边界。但是,在开始之前,您需要了解 Gradle 如何允许您使用不同的应用程序版本。

构建类型

默认情况下,有两种构建类型 debug 和 release。它们之间的唯一区别是 debuggable 参数的值。换句话说,您可以使用调试版本查看日志并调试应用程序,而发布版本则用于将您的应用程序发布到 Google Play 商店。您可以通过在 android 模块级 build.gradle 文件的块中添加以下代码来为构建类型配置属性:

buildTypes {
    release {

    }
    debug {

    }
}

在 debug 和 release 块中,您可以指定应用程序的特定于类型的设置。

Build Signing

构建的最重要的配置之一是其签名。没有签名,您将无法发布您的应用程序,因为有必要验证您是否是特定应用程序的所有者。尽管您无需签署调试版本(Android Studio会自动进行签名),但发行版本应由开发人员签名。

当你的密钥库已准备就绪,下面添加的代码位于 android 块下,与上述 buildTypes 块处于 module 层级的的 build.gradle 文件:

signingConfigs {
    release {
        storeFile file("path to your keystore file")
        storePassword "your store password"
        keyAlias "your key alias"
        keyPassword "your key password"
    }
}

在 signingConfigs 块中,为构建类型指定签名信息。注意密钥库文件路径。应该相对于模块目录进行指定。换句话说,如果您在模块目录中创建了密钥库文件并将其命名为“ keystore.jks”,则应指定的值将等于文件名。

更新 buildTypes 块以自动签署发布版本:

release {
    signingConfig signingConfigs.release
}

注意:与密钥库文件相关的两个重要注意事项:

  1. 将应用发布到Google Play商店后,后续提交必须使用相同的密钥库文件和密码,以确保安全。
  2. 确保不要将密钥库密码提交给版本控制系统,例如GitHub。您可以通过以下方式进行操作:将密码保存在与中不同的文件中build.gradle(例如keystorePassword.gradle,在Signing目录中),然后build.gradle通过以下方式从应用程序模块级别引用该文件:
apply from: "../Signing/keystorePassword.gradle

然后确保保持 keystorePassword.gradle 版本控制系统忽略它。其他技术包括将密码保存在 OS 级环境变量中,尤其是在远程持续集成系统(例如 CircleCI )上。

Build Flavors

为了创建您的应用程序的多个版本,您需要使用 productflavors。Flavors 是一种区分应用程序属性的方法,无论它是免费/付费的,分阶段的/生产的等等。

您将使用不同的应用程序名称来区分您的应用程序风格。首先,将以下名称添加为 strings.xml 文件中的字符串:

<string name="app_name_free">Socializify Free</string>
<string name="app_name_paid">Socializify Paid</string>

并删除现有的:

<string name="app_name">test</string>

现在,原始 app_name 字符串不再可用,请编辑 AndroidManifest.xml 文件,并将在 application 中的 android:label="@string/app_name" 替换为 android:label="${appName}" 。

同时在 modle 层级 build.gradle 文件的 android 块中添加以下代码:

// 1
flavorDimensions "appMode"
// 2
productFlavors {
    // 3
    free {
        // 4
        dimension "appMode"
        // 5
        applicationIdSuffix ".free"
        // 6
        manifestPlaceholders = [appName: "@string/app_name_free"]
    }
    paid {
        dimension "appMode"
        applicationIdSuffix ".paid"
        manifestPlaceholders = [appName: "@string/app_name_paid"]
    }
}
  1. 您需要指定 flavorDimensions 以正确匹配构建类型。在当前示例中,只需要一个维度 - appMode。
  2. 在 productFlavors 指定具体的  flavors 和 具体的设置。在当前示例中,分别是 free 和 paid。
  3. 指定第一个 productFlavors 的名称为:free。
  4. 必须指定 dimension 参数值。这里 free flavor 属于 appMode dimension。
  5. 由于您要为免费和付费功能创建单独的应用程序,因此需要它们具有不同的应用程序标识符。该 applicationIdSuffix 参数定义了会被附加到一个 applicationId 上,从而让你的应用程序拥有唯一标识符。
  6. manifestPlaceholders 允许你在构建的时候修改 AndroidManifest.xml 中的属性。在当前示例中,会根据不同的版本来修改应用名称。

再次 sync project with  Gradle。项目同步后,运行 tasks 命令,并查看哪些内容发生了改变:

./gradlew tasks

 

您将获得与第一次运行此命令时类似的任务列表:

...
Build tasks
-----------
...
assembleDebug - Assembles all Debug builds.
assembleFree - Assembles all Free builds.
assemblePaid - Assembles all Paid builds.
assembleRelease - Assembles all Release builds.
...

可以发现,任务添加了一些新的选项。现在,每种构建类型和构建 flavors 都有自己单独的命令。

从上一个 ./gradlew assemble 任务中删除生成的输出文件夹,以便您可以在添加 buildTypes 和 productFlavors 之后看到明显的区别。运行命令:

rm -rf app/build/outputs/apk

然后

./gradlew assembleDebug

命令完成后,检查输出目录:

cd app/build/outputs/apk
ls -R

您将获得如下内容:

free   paid

./free:
debug

./free/debug:
app-free-debug.apk   output.json

./paid:
debug

./paid/debug:
app-paid-debug.apk   output.json

您应该生成两个应用 – freeDebug 和 paidDebug

什么是Build Variant

从上面的输出中,您实际生成的是不同的构建变体,它们是构建类型 (buildType) 和构建风格 (flavors)组合。也就是说,您有四个可能的构建变体– paidDebug,paidRelease,freeDebug 和 freeRelease。

现在您有两种不同的构建风格,但是,不同的名称不足以让您从中获利。相反,您将根据构建风格 (flavors)配置应用程序的行为!

现在我们在 MainActivity 中定义一个常量:

private static String PAID_FLAVOR = "paid";

在 onCreate 方法中添加如下变量:

if (BuildConfig.FLAVOR == PAID_FLAVOR) {
            Toast.makeText(this, "3453", Toast.LENGTH_SHORT).show();
   }

如果是付费版本,就会有个 toast 提示。当然,上面只是一个示例,大家后面

创建任务

有时,您需要构建系统执行更复杂的操作或以某种方式自定义构建过程。例如,您可能希望Gradle输出名称中包含构建日期的APK文件。一种可能的解决方案是创建自定义 Gradle 任务。

将以下代码添加到模块级别的 build.gradle 文件中,与 android block 处于同一级别:

// 1
task addCurrentDate() {
    // 2
    android.applicationVariants.all { variant ->
        // 3
        variant.outputs.all { output ->
            // 4
            def date = new Date().format("dd-MM-yyyy")
            // 5
            def fileName = variant.name + "_" + date + ".apk"
            // 6
            output.outputFileName = fileName
        }
    }
}

下面说下相关逻辑:

  1. 您定义一个 addCurrentDate() 任务。
  2. 您遍历所有输出构建变量。
  3. 您遍历所有 APK 文件。
  4. 您创建一个实例 Date 并设置其格式。
  5. 您创建一个新的文件名,将当前日期附加到初始名称之后。
  6. 您将新文件名设置为当前的 APK 文件。

现在,您需要在构建过程的特定时刻执行此任务。在 task addCurrentDate() 块下面添加以下代码:

gradle.taskGraph.whenReady {
    addCurrentDate
}

whenReady 当前图形中充满任务并准备开始执行时,块中指定的任务将被调用一次。在这里,您指定 addCurrentDate 任务的名称。

现在,返回命令行,并确保您位于根目录中。运行以下命令以组装构建:

./gradlew assemblePaidRelease

任务完成后,转到输出目录,检查是否正确命名了内部版本:

cd app/build/outputs/apk/paid/release/
ls

您应该得到类似的输出:

output.json paidRelease_12-29-2019.apk

如果您的任务正确执行,则所有构建都将使用此约定命名。

到此,关于 gradle 的介绍就到这里。当然这也只是入门,后续还有 gradle 插件等需要继续学习。