android - 如何在Android项目配置阶段在Gradle插件中运行自定义Gradle任务?

标签 android gradle build.gradle gradle-plugin

好吧,所以我一直在努力使它正常工作,我只想编写我的测试并将其推送到 Maven,这样我的站会更新就不会日复一日。

问题陈述:我有多个 android 项目,它们都需要相同的预配置。这包括声明 maven 存储库、设置 versionCodes 和 versionNames 以及其他 misc 配置项。将相同的 block 复制并粘贴到每个项目中或放置在本地 common.gradle 文件中,然后在项目级别 build.gradle 配置阶段应用和调用。

我的解决方案:将所有这些通用逻辑提取到一个独立的 gradle 插件中,让每个项目的 build.gradle 文件应用这个插件来接收这些配置事件。

我创建了一个独立的插件,对插件进行了覆盖,它看起来像这样:

class CommonManager: Plugin<Project> {
    override fun apply(target: Project) {
        println("APPLY FUNCTION HAS BEEN ENTERED")
        target.tasks.create("myPluginTask", ReleaseManager::class.java)
    }

ReleaseManager 类是一个扩展 DefaultTask 并创建要运行的任务的类。这是 gradle 文档中推荐的内容,从可测试性/可重用性的角度来看它是有意义的,该类看起来像这样:

abstract class ReleaseManager: DefaultTask() {
    @get:Input
    abstract val versionHistoryPath: Property<String>

    @TaskAction
    fun configureVersionsAndReleaseMeta() { // do work... }

根据我阅读过的文档和我浏览过的其他示例项目,这是正确设置的。我使用 java-library 而不是 java 构建了插件,只是为了让本地 .jar 文件指向我的 android 项目以进行快速测试。这些 build.gradle 文件之一的示例如下所示:

buildscript {

    repositories {
        google()
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }

    dependencies {
        // misc dependencies ...
        classpath files("libs/MyCustomPlugin-1.0-SNAPSHOT.jar")
    }
}


apply plugin: "com.myplugin.common"

myPluginTask {
    versionHistoryPath.set("sdk/version_history.txt")
}

subprojects {
    apply plugin: 'maven-publish'
    apply plugin: 'com.jfrog.artifactory'
    group = 'org.jfrog.test.gradle.publish'
}

我创建了对 .jar 的依赖并应用了插件,然后使用它需要运行的属性配置任务。但是,当日志输出时,该任务从不在配置阶段运行.如果我点击 myPluginTaks{} 配置定义旁边的播放箭头,它实际上运行良好。此时,我知道我正确地指向了 .jar,我可以访问我在我的插件类中创建的任务,并且我可以分别设置它的属性。我对使用 gradle 进行这种自定义工作比较陌生,想了解我做错了什么。让我概述一下我的思考过程和尝试过的调试步骤。

我的“Bug”声明:我希望任务 “myPluginTask” 在我将我的插件应用到我的 build.gradle 脚本中并配置任务后执行正确的输入。它当前没有执行任务。

想法和笔记:

  • 在创建任务时,我在插件应用函数中使用了 create 而不是 register。我的理解是,通过使用 create,我是在说“嘿,我想创建一个任务,我希望构建立即知道它”,而不是“嘿,这是一个任务定义,但是一旦它被实际调用就让它延迟加载”在执行端"

  • 我将 ReleaseManager 的实现作为单独的函数移到了插件类中,并在任务创建闭包中调用了这些函数。这样可行。据我了解,这是因为其中定义的任何内容都在构建配置阶段运行。如果需要,我可以使用 doFirstdoLast 闭包将其推迟到执行阶段。

  • 我的直觉是,我已经创建了一个任务并确保构建现在立即知道它,但至少在执行阶段之前它没有执行任务的计划并且需要一个触发器。该触发器是直接调用任务还是任务取决于将在执行阶段运行的任务。

如有任何帮助,我们将不胜感激。如果需要,很乐意提供任何其他信息。

最佳答案

下面的一位用户提供了一个有见地的 link这帮助我找到了解决方案。此时我对 Gradle 也有了更好的理解,可以更好地阐明我的问题。

TLDR;我的直觉是正确的。我已经成功创建了一个任务,但没有提供触发该任务的方法。您可以根据目标项目提供的任务来执行此操作。

重申一下,我的插件类如下所示:

class CommonManager: Plugin<Project> {
    override fun apply(target: Project) {
        println("APPLY FUNCTION HAS BEEN ENTERED")
        target.tasks.create("myPluginTask", ReleaseManager::class.java)
    }

我应用插件的模块级 build.gradle 文件具有以下内容:

apply plugin: "com.myplugin.common"
apply plugin: "com.android.library"

apply 函数将在我的插件中触发,任务将被创建。但是它不会运行。为此,我需要依赖目标构建中的另一个任务作为触发器。这实际上看起来像下面这样:

class CommonManager: Plugin<Project> {
    override fun apply(target: Project) {
        println("APPLY FUNCTION HAS BEEN ENTERED")
        target.tasks.create("myPluginTask", ReleaseManager::class.java) { task ->
            // Have target project create a dependency between its task and mine
            target.tasks.findByName("preBuild").dependsOn(task)
    }

“preBuild”是android插件提供的任务。在我的例子中,com.android.library 这导致了第二个问题。在构建我的项目时,插件会抛出一个错误,指出“preBuild”不是一个已定义的任务。起初我以为我只是无法引用 android 库提供的任务,但后来它击中了我。如果您查看我上面的模块 build.gradle 文件的代码块,您会注意到我首先定义了我的通用插件。这意味着在我的插件应用 block 触发时,插件不知道此任务,因为尚未应用 android 插件。

您可以先定义 android 插件并记录定义顺序很重要,但这不是一个实用的解决方案。但是,您可以像这样在目标项目上实现 afterEvaluate 闭包:

class CommonManager: Plugin<Project> {
    override fun apply(target: Project) {
        println("APPLY FUNCTION HAS BEEN ENTERED")
        target.tasks.create("myPluginTask", ReleaseManager::class.java) { task ->
            target.afterEvaluate {
                // Have target project create a dependency between its task and mine
                target.tasks.findByName("preBuild").dependsOn(task)
            }
    }

这将等待模块 build.gradle 文件的评估完成。因此,一旦我的插件应用 block 被触发,我的插件就会知道“preBuild”任务,因为在项目评估期间应用了 android 插件。

额外提示:我正在使用 create 在插件中创建我的任务。如果您正在使用寄存器,则不需要 afterEvaluate 闭包。如果你定义了一个,如果运行 gradle 7.0 或更高版本,插件将抛出运行时错误。 gradle 社区认为这是一种冗余。

关于android - 如何在Android项目配置阶段在Gradle插件中运行自定义Gradle任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69510328/

相关文章:

Android 服务器响应值不适合 ListView

kotlin - 如何使用 Gradle Kotlin 脚本创建胖 JAR?

gradle - Gradle 中 "def"和 "static def"之间的区别

java - 编写任务执行(预/后)脚本 [Gradle + IntelliJ]

java - 重复 Android 抬头通知

java - ObjectOutputStream.writeBytes(String s) 意外的输出值

gradle - Gradle 任务示例上的 Groovy 语法

android - 为什么 Gradle 需要这么长时间来构建?

java - 与线程模式混淆

Java 不信任 Windows 上的任何 SSL 证书