Android - 根据构建类型更改flavor版本名称

30

我想为应用程序变体更改版本名称,但仅在调试构建时进行。

(例如,调试构建将具有类似于 1.0.1 D (DEBUG) 555 或 1.0.1 P (DEBUG) 555 的版本,但我希望仅发布构建具有类似于 1.0.1 的版本) 我该如何实现这一点?

基本上,我有这些构建类型:

buildTypes {


    debug {
        versionNameSuffix " (DEBUG) " + mBuild

    }
    release {
        runProguard true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), file('proguard-project.txt')
        signingConfig signingConfigs.release
    }
}

还有这些不同 API 环境所对应的口味:

productFlavors {
    dev {
        versionName = android.defaultConfig.versionName + " D"
    }
    prod {
        versionName = android.defaultConfig.versionName + " P"
    }
}

有没有办法在不改变产品口味版本名称的情况下制作发布版本?

我尝试通过动态设置版本名称来实现

    buildTypes.each { buildType ->
    if(buildType.name == 'debug') {
        productFlavors.dev.versionName = android.defaultConfig.versionName + " D"
    }
}

但这导致

在 GroupableProductFlavorDsl 容器中找不到属性 'dev'。


请接受您自己的答案,这样社区就清楚地知道问题已解决。 - Sergii Pechenizkyi
1
明天你可以接受自己的答案。 - martinpelant
6个回答

35

经过数小时的搜索,我已经成功使用此代码删除了发布版本构建的所有版本名称更改。

applicationVariants.all { variant ->
    if (variant.buildType.name == 'release') {
        variant.mergedFlavor.versionName = android.defaultConfig.versionName;
    }
}

这个符号(android.defaultConfig.versionName)在我升级AndroidStudio从0.5.5到0.8.1之前一直有效。现在有什么替代方案吗? - Gavriel
2
我遇到了一个“在项目上找不到属性'applicationVariants'”的错误。 - Micky
2
使用applicationVariants.each而不是applicationVariants.all - San
令我惊讶的是,这对于 android.libraryVrariants.all 也适用。 - user3829751
1
这不起作用,因为此代码在BuildConfig.java中创建了一个新变量“versionName”,而不是更新AndroidManifest.xml中的现有版本。 - Vipul Asri
1
我收到了错误信息:ERROR: versionCode不能直接在mergedFlavor上设置。 - Darush

3

对于那些想要使用Kotlin DSL的人,刚开始尝试时可能无法将新值分配给版本名称。

enter image description here

上面的图片显示ProductFlavor类中没有versionName的setter方法。 尝试1(强制转换为ProductFlavorImpl):
applicationVariants.forEach { variant ->
  if (variant.buildType.name != "release") {
    variant.mergedFlavor.let {
      it as ProductFlavorImpl
      it.versionName = "sampingan-${defaultConfig.versionName}"
    }
  }
}

it as ProductFlavorImpl 仍然无法工作,因为 MergedFlavor 无法转换成 ProductFlavorImpl 并抛出此错误:

com.android.builder.core.MergedFlavor cannot be cast to com.android.build.gradle.internal.api.dsl.model.ProductFlavorImpl

尝试2(强制转换为MergedFlavor):

  //
  variant.mergedFlavor.let {
    it as com.android.builder.core.MergedFlavor
  }
  // 

经过尝试和错误,看起来我们无法直接使用MergedFlavor更改versionName,而是出现了下面的另一个错误日志:

versionName cannot be set on a mergedFlavor directly.
versionNameOverride can instead be set for variant outputs using the following syntax:
android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.versionNameOverride = "1.0.0"
        }
    }
}

尝试3(使用ApplicationVariant对象):
因此,让我们将我们的实现更改为以下内容。
    applicationVariants.all(object : Action<com.android.build.gradle.api.ApplicationVariant> {
        override fun execute(variant: com.android.build.gradle.api.ApplicationVariant) {
            println("variant: ${variant}")
            variant.outputs.all(object : Action<com.android.build.gradle.api.BaseVariantOutput> {
                override fun execute(output: com.android.build.gradle.api.BaseVariantOutput) {

                    if (variant.buildType.name != "release") {
                    (output as com.android.build.gradle.internal.api.ApkVariantOutputImpl)
                            .versionNameOverride = "prefix-${variant.versionName}"
                    }
                }
            })
        }
    })


这种方法的灵感来自 @david-mihola 的回答。他解释说,groovy 有它自己的魔法 here
如果你想为每个不同的 buildTypesproductFlavors 更改 APK 名称,你可以参考 @david-mihola 的回答 here

1

最新的简单解决方案已经成功测试。在其中定义productflavour和buildTypes,并删除versionName。

使用output.versionNameOverride = versionName,我们可以根据buildType和productFlavour更改versionName。

代码:

 applicationVariants.all { variant ->
    variant.outputs.all { output ->
        def flavor = variant.getFlavorName()
        def versionName = "1.0.0"
        switch (flavor){
            case "paid":
                flavor = "Paid"
                if (variant.buildType.name == 'release') {
                    versionName = "1.0.0.8"
                } else if (variant.buildType.name == 'staging') {
                    versionName = "1.0.0.8"
                } else {
                    versionName = "1.0.0.8"
                }
                break
            case "free":
                flavor = "Free"
                if (variant.buildType.name == 'release') {
                    versionName = "1.0.0.14"
                } else if (variant.buildType.name == 'staging') {
                    versionName = "1.0.0.14"
                } else {
                    versionName = "1.0.0.14"
                }
                break
            case "trial":
                flavor = "Trial"
                if (variant.buildType.name == 'release') {
                    versionName = "1.0.0.3"
                } else if (variant.buildType.name == 'staging') {
                    versionName = "1.0.0.3"
                } else {
                    versionName = "1.0.0.3"
                }
                break
        }
        output.versionNameOverride = versionName
        outputFileName = "${flavor}_v${versionName}.apk"
    }
}

0

Build Type 应该覆盖 Product Flavor。请尝试下一个。

buildTypes {

    release {
        versionName = android.defaultConfig.versionName
    }
}

10
我已经尝试过了。问题在于构建类型没有versionName属性,只有versionNameSuffix。上面的代码会导致“按需创建属性(即动态属性)已被弃用,请阅读http://gradle.org/docs/current/dsl/org.gradle.api.plu上有关替换动态属性的内容。 在“BuildTypeDsl_Decorated”上已废弃动态属性:“versionName”。 - martinpelant
出现错误:RROR: 无法为BuildType_Decorated设置未知属性'versionName' - Darush

0
如果有人正在使用Gradle Kotlin DSL,你可以像这样编写下面的代码:
flavorDimensions.add("fruit")

productFlavors {
    create("apple") {
        dimension = "fruit"
    }
    create("tomato") {
        dimension = "fruit"
        versionName = "0.0.1-vegetable"
    }
}

当前Gradle版本为8.0.2

-1
我想为调试构建设置不同的versionName:
android {
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            if (variant.buildType.name == 'debug') {
                output.versionNameOverride = "1"
            }
        }
    }
}

1
@Marius请确保你已经将代码放在正确的位置。我们在生产应用程序中使用完全相同的代码,没有任何问题。 - Darush
我已经在不同的地方测试过它,版本没有被覆盖。我甚至在一个新项目中进行了测试,并在构建后查看了 BuildConfig 文件。也许你需要在回答中明确指定放置位置。 - mbo
工作解决方案 - Arul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接