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

Posted

技术标签:

【中文标题】如何使用 gradle 在 APK 文件名中设置 versionName?【英文标题】:How to set versionName in APK filename using gradle? 【发布时间】:2013-08-22 08:27:05 【问题描述】:

我正在尝试在 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)

【问题讨论】:

【参考方案1】:

我只需在一处更改版本名称。代码也很简单。

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

请注意,此解决方案适用于 APK 和 App Bundles (.aab files)

另请参阅:How to change the proguard mapping file name in gradle for android project

#最近 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.6.4(2020 年 8 月) 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)

我会在新版本出来时更新这篇文章。

#Solution 仅在 1.1.3-1.3.0 版本上测试 以下解决方案已使用以下 Android Gradle 插件版本进行测试:

1.3.0 (2015/07/30) - 不工作,bug scheduled to be fixed in 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"
    

【讨论】:

我认为这是正确的方法,而不是编写另一个任务来重命名文件。 如果你有强迫症并且不希望 AS 警告你 +,只需更改为 archivesBaseName = "MyCompany-MyAppName-$versionName" 很棒的发现,但不适用于具有不同版本代码的风味。它们都以相同的版本代码结束。 有什么办法可以在名字后面加上variant.buildType.name?我知道这实际上与默认配置无关,但我正在尝试弄清楚如何删除过时的 variantOutput.getAssemble() 警告 是否可以从 apk 名称中删除最后一个 '-debug' / '-release'?【参考方案2】:

这解决了我的问题:使用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")) 
        
           

更新:

所以这似乎不适用于 0.14+ 版本的 android studio gradle 插件。

这可以解决问题(参考来自question ) :

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

【讨论】:

如果我在AndroidManifest.xml 中定义了versionName 而不是gradle 配置,你知道如何让它工作吗?它现在给我myapp-release-null.apk 此答案不适用于 0.14+ 版本的 gradle 插件。有任何更新可以使用这些吗? @withoutclass 我问了这个问题并在这里得到了回答:***.com/questions/27068505/… 对于更新到 Gradle 4 的用户:将 each 更改为 all 并将 output.outputFile 更改为 outputFileName。如果有人确认这是可行的,则可以将其编辑为答案:) @phpirate:几乎可以工作:Error:(34, 0) Cannot set the value of read-only property 'name'【参考方案3】:

(经过编辑以使用 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 年 13 月 10 日)10:47 进行编译,您将获得以下文件名,具体取决于您选择的风格和构建类型:

开发调试:myProject_dev_debug_1.3.6_131016_1047.apk 开发版本:myProject_dev_release_1.3.6_131016_1047.apk prod 调试:myProject_prod_debug_1.2.0_131016_1047.apk 产品发布:myProject_prod_release_1.2.0_131016_1047.apk

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

【讨论】:

很好的解决方案。我试过了,它非常适合我的问题。谢谢! 是否可以在 Xamarin Studio 中使用相同的方法? 如果可能的话,那就太好了,但我现在开始学习 Xamarin 课程,但我仍然没有足够的练习来知道它是否可能。我会问这个问题,然后再来这里。 课程老师的评论:“有一个选项,您可以使用命令来更改生成文件的名称”。因此,从 Xamarin 中使用的方法必须与我为 Android Studio 编写的方法不同,抱歉。 解决错误无法设置只读属性'outputFile'的值 - 正如前面评论中提到的,必须“将each更改为alloutput.outputFileoutputFileName " - 这篇文章提供了一些细节:***.com/a/44265374/2162226【参考方案4】:

总结一下,对于那些不知道如何在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")) 
        
           

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

如果您在build.gradle 文件中设置versionCodeversionName,如下所示:

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 脚本增加版本号后生效? @Guy 抱歉拖了这么久。我编辑了答案,看看能不能解决你的问题。【参考方案5】:

如果您未在 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)

【讨论】:

相信随着gradle以后的版本,现在是com.android.builder.core.DefaultManifestParser【参考方案6】:

就我而言,我只是想找到一种方法来自动为releasedebug 变体生成不同的apk 名称。我通过将这个 sn-p 作为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

【讨论】:

【参考方案7】:

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.outputFileoutputFileName,this answer 的想法现在是:

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

【讨论】:

知道如何为 gradle 6 解决这个问题吗?【参考方案8】:

另一种选择是使用以下内容:

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

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

【讨论】:

对不起不起作用(不再):No such property: archivesBaseName for class: org.gradle.api.internal.project.DefaultProject_Decorated 你用的是什么gradle版本?【参考方案9】:

按照@Jon answer重命名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"
        
    

【讨论】:

这个不错!我更喜欢这种方式,而不是我目前这样做的其他方式。【参考方案10】:

有很多答案是正确的,无论是完整的还是经过一些修改的。但是我还是要添加我的,因为我遇到了所有问题,因为我使用脚本通过挂钩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 会做的是:

注入版本代码/名称-> 执行预构建操作-> 替换 apk 的名称

【讨论】:

你在哪里设置生成的versionCode和versionName变量? 我记得那是在我们的自定义 gradle 插件中完成的。它的执行被称为 preBuild 任务的最后一个动作。【参考方案11】:
    applicationVariants.all  variant ->
        variant.outputs.all  output ->
            output.outputFileName = output.outputFileName.replace(".apk", "-$variant.versionName.apk")
        
    

【讨论】:

虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。【参考方案12】:

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

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

 buildTypes 
        release 

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


        
        debug 

            defaultConfig 
                debuggable true

                versionNameSuffix "-DEBUG"
            
        
    

【讨论】:

这不会更改 APK 文件名。 事实上,这是一个不错的提示。不是在正确的问题,但很好。我在哪里可以阅读更多关于它的信息?是否可以基于 GIT 分支使用versionNameSuffix?例如,如果它不在“master”上,则始终有一个后缀,即使它是发布版本【参考方案13】:

对于最新的 gradle 版本,您可以使用以下 sn-p:

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

 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 名称中??【参考方案14】:

从 Android Studio 1.1.0 开始,我发现这种组合在 build.gradle 文件的 android 正文中有效。这是如果您不知道如何导入清单 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"))
                
            
        
    

【讨论】:

【参考方案15】:

正如我回答的here 如果您想将版本名称和版本代码附加到输出文件中,请执行以下操作:

applicationVariants.all  variant ->
        variant.outputs.all 
            def versionName = variant.versionName
            def versionCode = variant.versionCode
            def variantName = variant.name
            outputFileName = "$rootProject.name" + '_' + variantName + '_' + versionName + '_' + versionCode + '.apk'
        
    

【讨论】:

【参考方案16】:

您还可以在 apk 名称中添加格式化的构建时间,如下所示:

setProperty("archivesBaseName", "data-$versionName " + (new Date().format("HH-mm-ss")))

【讨论】:

以上是关于如何使用 gradle 在 APK 文件名中设置 versionName?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 build.gradle 文件中设置属性以在 Java 中访问该属性

如何使用 JAVA_OPTS 在 gitlab-ci.yaml 中设置 Gradle 代理变量

如何在 build.gradle.kts 中设置 openApi 生成器全局属性

如何在 Android Studio 和 Gradle 中设置 -source 1.7

如何在android APP中设置系统语言

Android studio加快编译速度