【问题标题】:How to set versionName in APK filename using gradle?如何使用 gradle 在 APK 文件名中设置 versionName?
【发布时间】: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)

【问题讨论】:

    标签: android build gradle apk android-gradle-plugin


    【解决方案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 我问了这个问题并在这里得到了回答:stackoverflow.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 " - 这篇文章提供了一些细节:stackoverflow.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.outputFileoutputFileNamethis 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")))
          

          【讨论】:

            猜你喜欢
            • 2018-04-30
            • 1970-01-01
            • 2020-10-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-31
            相关资源
            最近更新 更多