39

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

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

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

4

7 回答 7

70

你可以使用这样的东西:

defaultConfig {
  applicationId "com.test.app"
  versionCode 1
  versionName "1.0"
  setProperty("archivesBaseName", applicationId + "-v" + versionCode + "(" + versionName + ")")
}
于 2018-09-26T01:53:13.563 回答
25

作为Martin Zeitlers 回答的更通用方式,以下将侦听添加的任务,然后为添加的任何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)
    }
}
于 2019-01-02T16:49:28.890 回答
6

现在我已经为跨平台 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
    }
}

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

于 2018-09-26T16:01:10.287 回答
6

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

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

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

构建.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。

于 2019-12-06T22:38:16.417 回答
2

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

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

  • 签署生成的 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)
            }
        }
    }

它可以完美地与任何flavors,dimensionsbuildTypes. 没有任何额外的任务,适用于为输出设置的任何路径,Toolbar -> Generate signed Bundle可以为任何设置一个唯一的名称flavor

于 2022-01-28T11:01:53.900 回答
1

我发现了一个更好的选择,可以在生成 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}")

    ...
}

归功于网站和这篇文章

于 2019-12-06T03:51:33.573 回答
0

根据 Martin Zeitler 的回答,我在 Windows 上执行了此操作:

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

在我的应用程序的模块 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

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

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

于 2020-02-10T10:21:28.690 回答