You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gradle 7构建Android项目报错:Cannot run Project.afterEvaluate(Action)

问题概述
  • 项目类型:Android
  • Gradle wrapper版本:gradle-7.5
  • Gradle插件版本:7.4.2
  • 执行命令:./gradlew assembleDevGoogleRelease
  • 报错信息:

    Cannot run Project.afterEvaluate(Action) when the project is already evaluated.

  • 报错位置:build.gradle中exec { ... }代码块

问题原因

Gradle 7.x对任务执行阶段的API使用做了更严格的生命周期限制:在任务的doLast(执行阶段)中直接调用exec闭包时,内部逻辑会尝试触发afterEvaluate(项目评估阶段)的操作,但此时项目评估已经完成,从而触发冲突。Gradle 6.x无此严格限制,因此之前版本可正常运行。

另外原代码中存在变量错误:dirName未定义,会导致后续找不到APK目录,需同步修正。

解决方案

方案一:改用project.exec显式调用

修改doLast中的exec调用逻辑,避免隐式触发评估阶段操作,同时修正dirName变量:

android.applicationVariants.all { variant ->
    // 修正dirName为variant.dirName,获取变体对应的目录名(如devGoogle/release)
    def dirPath = "${project.projectDir.absolutePath}/build/outputs/apk/${variant.dirName}/"
    def filePath = ''
    variant.outputs.all {
        outputFileName = "xxx.apk"
        filePath = outputFileName
    }

    variant.getAssembleProvider().get().doLast {
        if (variant.buildType.name == 'release') {
            def cmd = "cd .. && ./ossutilmac64 cp -f ${dirPath}${filePath} oss://android-test-sz/${filePath}"
            // 显式创建输出流,避免隐式引用项目上下文
            def outputStream = new ByteArrayOutputStream()
            // 使用project.exec显式调用
            project.exec {
                executable 'zsh'
                args '-c', cmd
                standardOutput = outputStream
            }
            println(outputStream.toString())
        }
    }
}

方案二:创建独立上传任务(推荐,更符合Gradle设计)

将上传逻辑封装为独立任务,通过任务依赖关联到assemble任务,彻底规避生命周期冲突:

android {
    // ...其他配置

    flavorDimensions "app", "channel"
    productFlavors {
        dev {
            dimension "app"
            applicationIdSuffix ".dev"
        }

        product {
            dimension "app"
        }

        google {
            dimension "channel"
        }
    }

    // 将变体处理逻辑移到productFlavors外部,避免嵌套问题
    applicationVariants.all { variant ->
        def dirPath = "${project.projectDir.absolutePath}/build/outputs/apk/${variant.dirName}/"
        def filePath = "xxx.apk"

        variant.outputs.all {
            outputFileName = filePath
        }

        if (variant.buildType.name == 'release') {
            // 为每个release变体创建独立的上传任务
            def uploadTask = tasks.create(name: "upload${variant.name.capitalize()}ToOss", type: Exec) {
                executable 'zsh'
                args '-c', "cd .. && ./ossutilmac64 cp -f ${dirPath}${filePath} oss://android-test-sz/${filePath}"
                def outputStream = new ByteArrayOutputStream()
                standardOutput = outputStream
                doLast {
                    println(outputStream.toString())
                }
            }
            // 设置assemble任务完成后自动执行上传任务
            variant.assembleProvider.get().finalizedBy(uploadTask)
        }
    }
}

内容的提问来源于stack exchange,提问作者Jospehus Chou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:23:14