如何使用gradle在APK文件名中设置versionName?


169

我正在尝试在gradle自动生成的APK文件名中设置特定的版本号。

现在gradle生成了,myapp-release.apk但我希望它看起来像myapp-release-1.0.apk

我尝试重命名似乎很杂乱的选项。有没有简单的方法可以做到这一点?

buildTypes {
    release {
       signingConfig signingConfigs.release
       applicationVariants.each { variant ->
       def file = variant.outputFile
       variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" +    defaultConfig.versionName + ".apk"))
    }
}

我没有运气尝试过上面的代码。有什么建议?(使用gradle 1.6)

Answers:


225

我只需要在一个地方更改版本名称。代码也很简单。

下面的示例将创建一个名为MyCompany-MyAppName-1.4.8-debug.apkMyCompany-MyAppName-1.4.8-release.apk的 APK文件,具体取决于所选的构建变体。

请注意,此解决方案适用于APK和App Bundle(.aab文件)

另请参见:如何在Android项目的gradle中更改proguard映射文件名

最新Gradle插件的解决方案

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.company.app"
        minSdkVersion 13
        targetSdkVersion 21
        versionCode 14       // increment with every release
        versionName '1.4.8'   // change with every release
        setProperty("archivesBaseName", "MyCompany-MyAppName-$versionName")
    }
}

上述解决方案已通过以下Android Gradle插件版本进行了测试:

  • 3.5.2(2019年11月)
  • 3.3.0(2019年1月)
  • 3.1.0(2018年3月)
  • 3.0.1(2017年11月)
  • 3.0.0(2017年10月)
  • 2.3.2(2017年5月)
  • 2.3.1(2017年4月)
  • 2.3.0(2017年2月)
  • 2.2.3(2016年12月)
  • 2.2.2
  • 2.2.0(2016年9月)
  • 2.1.3(2016年8月)
  • 2.1.2
  • 2.0.0(2016年4月)
  • 1.5.0(2015/11/12)
  • 1.4.0-beta6(2015/10/05)
  • 1.3.1(2015/08/11)

随着新版本的发布,我将更新这篇文章。

解决方案仅在版本1.1.3-1.3.0中进行了测试

以下解决方案已通过以下Android Gradle插件版本进行了测试:

  • 1.3.0(2015/07/30)-无法正常运行错误计划在1.3.1中修复
  • 1.2.3(2015/07/21)
  • 1.2.2(2015/04/28)
  • 1.2.1(2015/04/27)
  • 1.2.0(2015/04/26)
  • 1.2.0-beta1(2015/03/25)
  • 1.1.3(2015/03/06)

应用程式Gradle档案:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"
    defaultConfig {
        applicationId "com.company.app"
        minSdkVersion 13
        targetSdkVersion 21
        versionCode 14       // increment with every release
        versionName '1.4.8'   // change with every release
        archivesBaseName = "MyCompany-MyAppName-$versionName"
    }
}

11
我认为这是正确的方法,而不是编写另一个重命名文件的任务。
Nandish A

5
只是更改为archivesBaseName =“ MyCompany-MyAppName- $ versionName”,如果您有OCD且不希望AS向您发出+
ligi的

4
很好的发现,但不适用于具有不同版本代码的风味。它们最终都具有相同的版本代码。
weston

2
有什么办法可以添加variant.buildType.name名称?我知道这并不是真的与默认配置有关,但是我试图弄清楚如何删除过时的variantOutput.getAssemble()警告
Allan W

2
是否可以从APK名称中删除最后一个“ -debug” /“-release”?
ilyamuromets

173

这解决了我的问题:使用applicationVariants.all代替applicationVariants.each

buildTypes {
      release {
        signingConfig signingConfigs.release
        applicationVariants.all { variant ->
            def file = variant.outputFile
            variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk")) 
        }
    }       
}

更新:

所以看来这不适用于Android Studio Gradle插件的0.14+版本。

这可以解决问题(此问题的参考 ):

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
        }
    }
}

3
如果我versionName定义了AndroidManifest.xml而不是gradle config,您知道如何使其工作吗?现在给了我myapp-release-null.apk
Iwo Banas

1
这个答案不适用于gradle插件的0.14+版本。有任何更新可以使用这些吗?
阿盖尔2014年

1
@withoutclass我问这是它自己的问题,并在这里得到了回答:stackoverflow.com/questions/27068505/…–
Argyle

2
对于人们更新到摇篮4:改eachalloutput.outputFileoutputFileName。如果有人对此工作表示怀疑,可以将其编辑为答案:)
PHPirate

6
@PHPirate:几乎可以使用:Error:(34, 0) Cannot set the value of read-only property 'name'
Mooing Duck

47

(已编辑,可与Android Studio 3.0和Gradle 4一起使用)

我一直在寻找一个更复杂的apk文件名重命名选项,我写了这个,希望对其他任何人都有用。它使用以下数据重命名apk:

  • 味道
  • 构建类型
  • 日期

我对gradle类进行了一些研究,并从其他答案中进行了一些复制/粘贴。我正在使用gradle 3.1.3

在build.gradle中:

android {

    ...

    buildTypes {
        release {
            minifyEnabled true
            ...
        }
        debug {
            minifyEnabled false
        }
    }

    productFlavors {
        prod {
            applicationId "com.feraguiba.myproject"
            versionCode 3
            versionName "1.2.0"
        }
        dev {
            applicationId "com.feraguiba.myproject.dev"
            versionCode 15
            versionName "1.3.6"
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def project = "myProject"
            def SEP = "_"
            def flavor = variant.productFlavors[0].name
            def buildType = variant.variantData.variantConfiguration.buildType.name
            def version = variant.versionName
            def date = new Date();
            def formattedDate = date.format('ddMMyy_HHmm')

            def newApkName = project + SEP + flavor + SEP + buildType + SEP + version + SEP + formattedDate + ".apk"

            outputFileName = new File(newApkName)
        }
    }
}

如果今天(2016年10月13日)在10:47进行编译,则将根据您选择的样式和构建类型获得以下文件名:

  • 开发人员调试:myProject_ dev_debug_1.3.6 _131016_1047.apk
  • 开发版本:myProject_ dev_release_1.3.6 _131016_1047.apk
  • 产品调试:myProject_ prod_debug_1.2.0 _131016_1047.apk
  • 产品发布:myProject_ prod_release_1.2.0 _131016_1047.apk

注意:未对齐的版本apk名称仍然是默认名称。


很好的解决方案。我尝试过,它非常适合我的问题。谢谢!
Pabel

Xamarin Studio是否可以使用相同的方法?
亚历山德罗·卡利亚洛

如果可以的话,那会很棒,但是我现在正在开始一个Xamarin课程,但是我仍然没有足够的实践来知道是否可能。我会问这个问题,然后再来这里。
2016年

该课程老师的评论:“有一个选项,您可以在其中使用命令来更改生成的文件的名称”。因此,很抱歉,Xamarin中使用的方法必须与我为Android Studio编写的方法不同。
2016年

3
要解决此错误无法设置只读属性“OUTPUTFILE”的价值 -如前面提到的注释为具有“改变eachalloutput.outputFileoutputFileName -这篇文章提供了有关的一些细节:stackoverflow.com/a/44265374/2162226
Gene Bo

19

总结一下,对于那些不知道如何导入程序包的人build.gradle(例如我),请使用以下代码buildTypes

buildTypes {
      release {
        signingConfig signingConfigs.release
        applicationVariants.all { variant ->
            def file = variant.outputFile
            def manifestParser = new com.android.builder.core.DefaultManifestParser()
            variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile) + ".apk")) 
        }
    }       
}

=====编辑=====

如果您像这样设置versionCodeversionName,则build.gradle

defaultConfig {
    minSdkVersion 15
    targetSdkVersion 19
    versionCode 1
    versionName "1.0.0"
}

您应该这样设置:

buildTypes {   
        release {
            signingConfig signingConfigs.releaseConfig
            applicationVariants.all { variant ->
                def file = variant.outputFile
                variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
            }
        }
}


======使用Android Studio 1.0编辑======

如果您使用的是Android Studio 1.0,则会收到如下错误:

Error:(78, 0) Could not find property 'outputFile' on com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated@67e7625f.

您应该将此build.Types部分更改为:

buildTypes {
        release {
            signingConfig signingConfigs.releaseConfig
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
                }
            }
        }
    }

这很好。但是,由于我在gradle构建中增加了清单版本,因此它将创建一个具有旧值(预先增加)的APK。在gradle脚本增加版本号后,是否有任何方法可以确保此方法生效?
盖伊

1
@Guy对不起,花了很长时间。我编辑了答案,看看它是否可以解决您的问题。
韦斯利

17

如果您未在defaultConfig块中指定versionName,defaultConfig.versionName则会导致null

要从清单中获取versionName,可以在build.gradle中编写以下代码:

import com.android.builder.DefaultManifestParser

def manifestParser = new DefaultManifestParser()
println manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)

7
我相信在gradle的更高版本中,它现在是com.android.builder.core.DefaultManifestParser
Ryan S

8

就我而言,我只是想找到一种方法来自动化生成不同apk名称的for releasedebugvariant。我设法通过将以下代码片段作为的子代来轻松实现此目的android

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def appName = "My_nice_name_"
        def buildType = variant.variantData.variantConfiguration.buildType.name
        def newName
        if (buildType == 'debug'){
            newName = "${appName}${defaultConfig.versionName}_dbg.apk"
        } else {
            newName = "${appName}${defaultConfig.versionName}_prd.apk"
        }
        output.outputFile = new File(output.outputFile.parent, newName)
    }
}

对于新的Android gradle插件3.0.0,您可以执行以下操作:

 applicationVariants.all { variant ->
    variant.outputs.all {
        def appName = "My_nice_name_"
        def buildType = variant.variantData.variantConfiguration.buildType.name
        def newName
        if (buildType == 'debug'){
            newName = "${appName}${defaultConfig.versionName}_dbg.apk"
        } else {
            newName = "${appName}${defaultConfig.versionName}_prd.apk"
        }
        outputFileName = newName
    }
}

这会产生类似: My_nice_name_3.2.31_dbg.apk


6

另一种选择是使用以下方法:

String APK_NAME = "appname"
int VERSION_CODE = 1
String VERSION_NAME = "1.0.0"

project.archivesBaseName = APK_NAME + "-" + VERSION_NAME;

    android {
      compileSdkVersion 21
      buildToolsVersion "21.1.1"

      defaultConfig {
        applicationId "com.myapp"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode VERSION_CODE
        versionName VERSION_NAME
      }

       .... // Rest of your config
}

这会将“ appname-1.0.0”设置为所有apk输出。


抱歉,无法正常工作(不再): No such property: archivesBaseName for class: org.gradle.api.internal.project.DefaultProject_Decorated
马丁

您正在使用什么gradle版本?
Marco RS

6

摇篮6+

我现在在Android Studio 4.0和Gradle 6.4中使用以下内容:

android {
    defaultConfig {
        applicationId "com.mycompany.myapplication"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 15
        versionName "2.1.1"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationVariants.all { variant ->
                variant.outputs.all {
                    outputFileName = "ApplicationName-${variant.name}-${variant.versionName}.apk"
                }
            }
        }
    }
}

摇篮4

语法在Gradle 4(Android Studio 3+)中有所更改(从output.outputFile变为outputFileName此答案的思路现在是:

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def newName = outputFileName
            newName.replace(".apk", "-${variant.versionName}.apk")
            outputFileName = new File(newName)
        }
    }
}

任何想法如何解决此gradle 6?
spartygw

@spartygw更新了答案
PHPirate

5

按照@Jon答案重命名apk的正确方法

defaultConfig {
        applicationId "com.irisvision.patientapp"
        minSdkVersion 24
        targetSdkVersion 22
        versionCode 2  // increment with every release
        versionName "0.2" // change with every release
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //add this line
        archivesBaseName = "AppName-${versionName}-${new Date().format('yyMMdd')}"
    }   

或者通过另一种方法可以达到相同的结果

android {
    ...

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def formattedDate = new Date().format('yyMMdd')
            outputFileName = "${outputFileName.replace(".apk","")}-v${defaultConfig.versionCode}-${formattedDate}.apk"
        }
    }
}

不错的一个!我现在比其他方式更喜欢这种方式。
Droid Chris

3

完全或进行一些修改后,有许多正确的答案。但是我还是要添加我的,因为我所有的人都遇到了问题,因为我使用脚本通过挂钩preBuild任务来动态生成VersionName和VersionCode 。

如果您正在使用类似的方法,那么下面的代码将起作用:

project.android.applicationVariants.all { variant ->
    variant.preBuild.doLast {
    variant.outputs.each { output ->
        output.outputFile = new File(
                output.outputFile.parent,
                output.outputFile.name.replace(".apk", "-${variant.versionName}@${variant.versionCode}.apk"))
        }
    }
}

解释:由于在第一个操作中我要覆盖版本代码和名称,因此preBuild必须将重命名文件添加到此任务的末尾。所以在这种情况下gradle会做的是:

注入版本代码/名称->执行preBuild操作->为APK替换名称


您在哪里设置生成的versionCode和versionName变量?
火星

我记得那是在我们的自定义gradle插件中完成的。它的执行被称为preBuild任务的最后一个动作。
伊戈尔·科尔达什(IgorČordaš),2013年

2
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            output.outputFileName = output.outputFileName.replace(".apk", "-${variant.versionName}.apk")
        }
    }

尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
罗萨里奥·佩雷拉·费尔南德斯

1

就我而言,我通过这种方式解决了这个错误

在调试版本中添加SUFFIX,在这种情况下,我将“ -DEBUG”文本添加到调试部署中

 buildTypes {
        release {

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


        }
        debug {

            defaultConfig {
                debuggable true

                versionNameSuffix "-DEBUG"
            }
        }
    }

这不会更改APK文件名。
汤姆(Tom),

1
实际上,这是一个不错的提示。不是正确的问题,而是一个好问题。我在哪里可以了解更多?是否可以versionNameSuffix基于GIT分支使用?例如,如果它不在“ master”上,即使它是发行版,也要始终有一个后缀
android开发人员

0

对于最新的gradle版本,您可以使用以下代码段:

首先设置您的应用清单清单位置

 sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
        {
    }

然后在build.gradle中

import com.android.builder.core.DefaultManifestParser

def getVersionName(manifestFile) {
    def manifestParser = new DefaultManifestParser();
    return manifestParser.getVersionName(manifestFile);
}

def manifestFile = file(android.sourceSets.main.manifest.srcFile);
def version = getVersionName(manifestFile)

buildTypes {
    release {
       signingConfig signingConfigs.release
       applicationVariants.each { variant ->
       def file = variant.outputFile
       variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" +    versionName + ".apk"))
    }
}

如果每种构建类型的清单不同,请进行调整。但由于我只有一个人-对我来说效果很好。


是否可以从类文件中向apk名称添加字符串?
Upendra Shah's

0

从Android Studio 1.1.0开始,我发现此组合适用于文件的android正文build.gradle。如果您不知道如何导入清单xml文件数据。我希望它能得到Android Studio的更多支持,但请尝试使用这些值,直到获得所需的apk名称输出为止:

defaultConfig {
        applicationId "com.package.name"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 6
        versionName "2"
    }
    signingConfigs {
        release {
            keyAlias = "your key name"
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", "appName_" + versionName + ".apk"))
                }
            }
        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.