【问题标题】:How to change the generated filename for App Bundles with Gradle?如何使用 Gradle 更改 App Bundle 的生成文件名?
【发布时间】:2018-09-26 01:32:08
【问题描述】:

因此,要更改 gradle android 中生成的 APK 文件名,我可以执行以下操作:

applicationVariants.output.all {
    outputFileName = "the_file_name_that_i_want.apk"
}

生成的 App Bundle 文件有类似的东西吗?如何更改生成的 App Bundle 文件名?

【问题讨论】:

  • 我不是要更改生成的 APK 文件名!我在询问更改生成的 App Bundle 文件名!它们不一样。
  • 撤回了我的近距离投票并添加了答案。

标签: android gradle android-gradle-plugin android-app-bundle


【解决方案1】:

你可以使用这样的东西:

defaultConfig {
  applicationId "com.test.app"
  versionCode 1
  versionName "1.0"
  setProperty("archivesBaseName", applicationId + "-v" + versionCode + "(" + versionName + ")")
}

【讨论】:

  • 是否也可以在文件名中添加风味类型?
  • 不太适合风味,如果您需要同时构建多个风味。
  • 又好又简单!为我工作。
  • 这适用于 Android Studio 3.5.2。你将在 apk 的末尾有 buildType-flavor。
  • 我们在最后自动添加了构建风格。这是最好的解决方案
【解决方案2】:

作为Martin Zeitlers answer 的更通用方式,以下将侦听添加的任务,然后为添加的任何bundle* 任务插入重命名任务。

只需将其添加到 build.gradle 文件的底部即可。

注意:它会添加不必要的任务,但这些任务将被跳过,因为它们与任何文件夹都不匹配。例如> Task :app:renameBundleDevelopmentDebugResourcesAab NO-SOURCE

tasks.whenTaskAdded { task ->
    if (task.name.startsWith("bundle")) {
        def renameTaskName = "rename${task.name.capitalize()}Aab"
        def flavor = task.name.substring("bundle".length()).uncapitalize()
        tasks.create(renameTaskName, Copy) {
            def path = "${buildDir}/outputs/bundle/${flavor}/"
            from(path)
            include "app.aab"
            destinationDir file("${buildDir}/outputs/renamedBundle/")
            rename "app.aab", "${flavor}.aab"
        }

        task.finalizedBy(renameTaskName)
    }
}

【讨论】:

  • 嗨,我试过这个,但这在我的场景中不起作用,因为我有多种口味,你能帮我做什么吗?
  • 如果我使用“Build -> Generate signed Bundle”,它对我不起作用。但是,如果您使用终端构建它,它就可以工作。 (按照命令 'gradlew :app:bundleFlavor')
  • 如果这不起作用,您的包含可能不匹配。尝试删除包含并重命名,然后查看是否复制了任何内容。
  • 目前无法正常工作,因为 Android Studio 有内置任务 rename "rename${task.name.capitalize()}Aab"。
  • 这对我有用!不过,我需要更改您的代码。而不是:include "app.aab" 我必须制作这个 include "app-${flavor}.aab" 而不是 rename "app.aab", "${flavor}.aab" 它需要是 rename "app-${flavor}.aab", "${flavor}.aab" 在此之后我对构建目录和文件名进行了一些其他调整,它工作得很好。
【解决方案3】:

现在我已经为跨平台 CLI 执行编写了一种 Exec 模板,无论 commandLine 是什么。我的RenameTask 可以检测Linux & Windows,以及release & debug

属性archivesBaseName需要在defaultConfig中定义:

android {
    defaultConfig {
        setProperty("archivesBaseName", "SomeApp_" + "1.0.0")
    }
}

RenameTask extends Exec 执行重命名(不要与type: Rename 混淆):

import javax.inject.Inject

/**
 * App Bundle RenameTask
 * @author Martin Zeitler
**/
class RenameTask extends Exec {
    private String buildType
    @Inject RenameTask(String value) {this.setBuildType(value)}
    @Input String getBuildType() {return this.buildType}
    void setBuildType(String value) {this.buildType = value}
    @Override
    @TaskAction
    void exec() {
        def baseName = getProject().getProperty('archivesBaseName')
        def basePath = getProject().getProjectDir().getAbsolutePath()
        def bundlePath = "${basePath}/build/outputs/bundle/${this.getBuildType()}"
        def srcFile = "${bundlePath}/${baseName}-${this.getBuildType()}.aab"
        def dstFile = "${bundlePath}/${baseName}.aab"
        def os = org.gradle.internal.os.OperatingSystem.current()
        if (os.isUnix() || os.isLinux() || os.isMacOsX()) {
            commandLine "mv -v ${srcFile} ${dstFile}".split(" ")
        } else if (os.isWindows()) {
            commandLine "ren ${srcFile} ${dstFile}".split(" ")
        } else {
            throw new GradleException("Cannot move AAB with ${os.getName()}.")
        }
        super.exec()
    }
}

它完成了另外两个任务:

// it defines tasks :renameBundleRelease & :renameBundleDebug
task renameBundleRelease(type: RenameTask, constructorArgs: ['release'])
task renameBundleDebug(type: RenameTask, constructorArgs: ['debug'])

// it sets finalizedBy for :bundleRelease & :bundleDebug
tasks.whenTaskAdded { task ->
    switch (task.name) {
        case 'bundleRelease': task.finalizedBy renameBundleRelease; break
        case   'bundleDebug': task.finalizedBy renameBundleDebug; break
    }
}

先进之处在于,它不会留下任何东西,并且可以将文件移动到任何想要的地方。

【讨论】:

  • 我得到了 app.aab 的重命名副本(留下两个文件)。如何删除 app.aab?根据时间戳,app.aap 似乎是在重命名后生成的,因此在同一个重命名任务中将其删除是行不通的。非常感谢任何帮助
  • @ScottB 无法使用Rename 任务删除;这将需要一个进一步的Delete 任务,其中dependsOn 那个Copy 任务(或Apache Ant 集成移动文件)。至少这种方法不会像公认的答案那样生成比所需更多的任务 - 它应该更好地与风味配合使用,因为它们中的每一个都有自己的最终任务名称。
  • @ScottB :我有同样的问题。你能得到解决方案吗?我尝试了 dependsOn ,但它没有删除旧文件。
  • 它不读取dependsOn 并且上面的Exec 任务正在运行。
  • 不错的解决方案,但您如何在 Windows 上做同样的事情?我尝试输入 ren 或 copy 而不是“mv”,但系统无法识别该命令!
【解决方案4】:

@SaXXuM 的解决方案效果很好!重命名工件不需要任务。您可以直接在android {} 块中调用setProperty()。我更喜欢在文件名中有:

  • 应用 ID
  • 模块名称
  • 版本名称
  • 版本代码
  • 日期
  • 构建类型

这是我在项目中使用它的方式:

build.gradle

apply from: "../utils.gradle"

android {
    ...
    setProperty("archivesBaseName", getArtifactName(defaultConfig))
}

utils.gradle

ext.getArtifactName = {
    defaultConfig ->
        def date = new Date().format("yyyyMMdd")
        return defaultConfig.applicationId + "-" + project.name + "-" + defaultConfig.versionName + "-" + defaultConfig.versionCode + "-" + date
}

结果是:

com.example-app-1.2.0-10200000-20191206-release.aab

它适用于 APK 和 AAB。

【讨论】:

  • 如果应用有不同的风格怎么办?
  • 最后是构建类型还是风格?
  • 这是最简单的方法。其他答案太复杂了。
【解决方案5】:

为什么没有人为此使用现有的 gradle 任务?

有一个 FinalizeBundleTask 类型的 gradle 任务,它被称为包生成的最后一步,它做两件事:

  • 签署生成的 AAB 包
  • 在请求的位置移动和重命名 AAB 包

您需要做的只是将此任务的“输出”更改为您想要的任何内容。此任务包含属性finalBundleFile - 最终 AAB 包的完整路径。

我正在使用它:

    applicationVariants.all {
        outputs.all {
            // AAB file name that You want. Falvor name also can be accessed here.
            val aabPackageName = "$App-v$versionName($versionCode).aab"
            // Get final bundle task name for this variant
            val bundleFinalizeTaskName = StringBuilder("sign").run {
                // Add each flavor dimension for this variant here
                productFlavors.forEach {
                    append(it.name.capitalizeAsciiOnly())
                }
                // Add build type of this variant
                append(buildType.name.capitalizeAsciiOnly())
                append("Bundle")
                toString()
            }
            tasks.named(bundleFinalizeTaskName, FinalizeBundleTask::class.java) {
                val file = finalBundleFile.asFile.get()
                val finalFile = File(file.parentFile, aabPackageName)
                finalBundleFile.set(finalFile)
            }
        }
    }

它与任何flavorsdimensionsbuildTypes 完美配合。没有任何额外的任务,可以使用在Toolbar -> Generate signed Bundle 中为输出设置的任何路径,可以为任何flavor 设置一个唯一的名称。

【讨论】:

    【解决方案6】:

    我发现了一个更好的选择,可以在您生成 apk/aab 时自动增加应用版本控制和自动重命名。解决方案如下(记得在根文件夹中创建“version.properties”文件:

    android {
         ...
         ...
        Properties versionProps = new Properties()
        def versionPropsFile = file("${project.rootDir}/version.properties")
        versionProps.load(new FileInputStream(versionPropsFile))
        def value = 0
        def runTasks = gradle.startParameter.taskNames
        if ('assemble' in runTasks || 'assembleRelease' in runTasks) {
            value = 1
        }
        def versionMajor = 1
        def versionPatch = versionProps['VERSION_PATCH'].toInteger() + value
        def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1
        def versionNumber = versionProps['VERSION_NUMBER'].toInteger() + value
        versionProps['VERSION_PATCH'] = versionPatch.toString()
        versionProps['VERSION_BUILD'] = versionBuild.toString()
        versionProps['VERSION_NUMBER'] = versionNumber.toString()
        versionProps.store(versionPropsFile.newWriter(), null)
    
        defaultConfig {
        applicationId "com.your.applicationname"
        versionCode versionNumber
        versionName "${versionMajor}.${versionPatch}.${versionBuild}(${versionNumber})"
        archivesBaseName = versionName
        minSdkVersion 26
        targetSdkVersion 29
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        signingConfig signingConfigs.release
        setProperty("archivesBaseName","${applicationId}-v${versionName}")
    
        ...
    }
    

    感谢this 网站和this 帖子

    【讨论】:

      【解决方案7】:

      根据 Martin Zeitler 的回答,我在 Windows 上这样做了:

      请注意,在我的设置中,.aab 文件是在发布文件夹中创建的,它会根据 bug report 删除该文件夹中的所有其他内容。

      在我应用的模块 gradle 中:

      apply from: "../utils.gradle"
      
      ...
      
      tasks.whenTaskAdded { task ->
          switch (task.name) {
              case 'bundleRelease':
                  task.finalizedBy renameBundle
                  break
          }
      }
      

      在 utils.gradle 中:

      task renameBundle (type: Exec) {
          def baseName = getProperty('archivesBaseName')
      
          def stdout = new ByteArrayOutputStream()
          def stderr = new ByteArrayOutputStream()
      
          commandLine "copy.bat", rootProject.getProjectDir().getAbsolutePath() + "\\release\\${baseName}-release.aab", "<MY_AAB_PATH>\\${baseName}.aab", "D:\\Android\\studio\\release"
          workingDir = rootProject.getProjectDir().getAbsolutePath()
          ignoreExitValue true
          standardOutput stdout
          errorOutput stderr
      
          doLast {
              if (execResult.getExitValue() == 0) {
                  println ":${project.name}:${name} > ${stdout.toString()}"
              } else {
                  println ":${project.name}:${name} > ${stderr.toString()}"
              }
          }
      }
      

      copy.bat 在项目文件夹中创建,包含以下内容:

      COPY %1 %2
      RMDIR /Q/S %3
      

      小心使用第三个参数,以确保您不使用对您很重要的文件夹。

      编辑:为什么 .BAT 用于您可能会问的 2 个命令。如果您尝试 commandLine "copy", ... 在 Windows 上会导致“系统无法识别命令副本”。放任何东西,比如 COPY、REN、RENAME 等,都不起作用。

      【讨论】:

        猜你喜欢
        • 2019-09-14
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多