为什么 Gradle 忽略发布{}并在调试版本上实施规则?

Why does Gradle disregard release{} and implement a rule on debug build as well?

我不确定这是否发生在以前,但我认为它发生在 Android Studio 及其 Gradle 最近更新之后。

也就是说,我正在尝试设置发布APK的输出路径。所以我做了这样的代码

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        signingConfig signingConfigs.config

        def outputPathName = "./apk-release.apk"
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = file(outputPathName)
            }
        }
    }
}

这会将 APK 从其默认位置 (/build/outputs/apk) 移至 build.gradle 文件旁边。

但是,release{} 被忽略,Android Studio 将调试版本移动到此位置并重命名它。因此,无论我创建签名的 APK 还是按调试图标来测试调试版本,APK 都会被移动和重命名。它应该留在默认位置,对吧?

为什么会这样? Android Studio Gradle 中的错误或我的代码中的错误?

注意:我注意到在我为 APK 创建自定义名称的其他项目中也发生了同样的情况。它还将重命名调试 APK 并以相同的方式忽略 release{}.

Android工作室版本:1.3。预览 5

the release{} is being disregarded

不是真的。 build.gradle 中的每一行 代码在处理脚本时执行。

Gradle 脚本不会在构建时执行代码。它们在那里定义构建过程的对象模型。在 Android Studio 中,Gradle 脚本不会在构建时读入和解释;它们会在项目打开时或您 "Sync Project with Gradle Files" 时读入。正是该对象模型填充了 Build Variants 视图之类的内容。

release 闭包并不是说 "this is only stuff that should be done on a release build"。它只是说 "hey, anything you can't recognize, like minifyEnabled, see if that's a property or method or something on this here release object"。您可以像这样编写 release 闭包的开始部分:

buildTypes {
    release.minifyEnabled false
    release.proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    release.signingConfig signingConfigs.config
}

甚至:

   buildTypes.release.minifyEnabled false
   buildTypes.release.proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
   buildTypes.release.signingConfig signingConfigs.config

如果你愿意的话。

这就是为什么您通常会在 android {} 的末尾看到那种 applicationVariants 循环,因为(我认为)applicationVariants 是 Gradle 的一部分Android 插件 DSL,它将遍历所有应用程序变体。

因此,如果您只想影响 release 构建,请在循环中检查 variant 的构建类型:

    def outputPathName = "./apk-release.apk"
    applicationVariants.all { variant ->
        def name = variant.buildType.name

        if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) {
            return; // Skip debug builds.
        }

        variant.outputs.each { output ->
            output.outputFile = file(outputPathName)
        }
    }

(可能有更巧妙的过滤方法,但这是我一直在使用的...)