如何在Gradle中的buildType上添加条件afterEvaluate

时间:2016-12-20 09:46:24

标签: android gradle android-gradle

我的build.gradle文件末尾有这段代码:

         project.afterEvaluate {

            // If you add/change build types, you have to add to/change
            // these task names.
            mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
            mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')

        }

有关完整代码,请参阅:Copy generated third party licenses to assets

这曾经工作正常(无论设置了哪个buildType),但如果将我的依赖项更新为最新版本,则会触发异常(使用buildType ='debug'构建时):

Could not get unknown property 'mergeReleaseAssets' for project ':application'

我的想法是,可能将此块拆分为两个并将它们置于buildTypes配置下。但这不起作用,因为它试图无论如何都要评估代码并崩溃。

有什么想法吗?

更新1:根本原因? https://code.google.com/p/android/issues/detail?id=219732

更新2:一个可怕的解决方法:

try {
    mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
} catch (Exception e) {
    // Expected when building variant Release
}
try {
    mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
} catch (Exception e) {
    // Expected when building variant Debug
}

2 个答案:

答案 0 :(得分:5)

您在afterEvaluate中引用发布任务时出错的原因可能是因为Android Studio的即时运行功能使用特殊Android Gradle plugin feature来构建 debug 应用程序变体。这意味着只创建 debug 任务,因此在您引用发布任务时无法找到它们。

有几种方法可以解决这个问题:

  1. 使用字符串按名称搜索依赖任务。如果Android构建系统将来更改任务名称,则您的其他构建规则将无法运行,但您可能甚至都没有注意到。

  2. 要确定是否存在发布任务,请检查是否存在名称将来不太可能更改的任务。也许assembleRelease符合这个法案。

  3. 要确定是否存在发布任务,请检查发布应用程序变体是否使用以下内容构建:

    project.afterEvaluate {
        if (!android.applicationVariants.matching { it.buildType.name == 'release' }.isEmpty()) {
            mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
        }
    }
    
  4. 最后一个选项看起来很糟糕,但希望如果Android构建系统任务名称在将来发生变化,它将会快速失败。

答案 1 :(得分:3)

在调试buildType的情况下出现异常的原因是因为未创建mergeReleaseAssets任务。您可以改为:

project.tasks.findByName('mergeReleaseAssets')?.dependsOn project.tasks.getByName('downloadLicenses')

甚至省略project

tasks.findByName('mergeReleaseAssets')?.dependsOn tasks.getByName('downloadLicenses')

这在可空的返回类型上使用安全导航操作符,因此它比try / catch解决方法更清晰。