如何使用 Gradle 更改为 App Bundle 生成的文件名?
How to change the generated filename for App Bundles with Gradle?
所以要更改 gradle android 中生成的 APK 文件名,我可以这样做:
applicationVariants.output.all {
outputFileName = "the_file_name_that_i_want.apk"
}
生成的App Bundle文件有没有类似的东西?如何更改生成的 App Bundle 文件名?
你可以使用这样的东西:
defaultConfig {
applicationId "com.test.app"
versionCode 1
versionName "1.0"
setProperty("archivesBaseName", applicationId + "-v" + versionCode + "(" + versionName + ")")
}
现在我已经为跨平台 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
}
}
先进之处在于,它不会留下任何东西,并且可以将文件移动到任何需要的地方。
作为 的更通用方法,以下内容将侦听添加的任务,然后为添加的任何 bundle*
任务插入重命名任务。
只需将其添加到 build.gradle
文件的底部即可。
Note: It will add more tasks than necessary, but those tasks will be skipped since they don't match any folder. e.g. > 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)
}
}
我发现了一个更好的选项,可以在您生成 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 website and this post
来自 @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。
根据 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
注意第三个参数,确保您没有使用对您来说很重要的文件夹。
编辑:为什么您可能会问 2 个命令的 .BAT。如果您在 Windows 上尝试 commandLine "copy",... 它会导致 "system does not recognize the command copy"。输入任何内容,例如 COPY、REN、RENAME 等,都不起作用。
为什么没有人为此使用现有的 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)
}
}
}
它与任何 flavors
、dimensions
和 buildTypes
完美配合。没有任何额外的任务,适用于 Toolbar -> Generate signed Bundle
中为输出设置的任何路径,可以为任何 flavor
.
设置唯一名称
所以要更改 gradle android 中生成的 APK 文件名,我可以这样做:
applicationVariants.output.all {
outputFileName = "the_file_name_that_i_want.apk"
}
生成的App Bundle文件有没有类似的东西?如何更改生成的 App Bundle 文件名?
你可以使用这样的东西:
defaultConfig {
applicationId "com.test.app"
versionCode 1
versionName "1.0"
setProperty("archivesBaseName", applicationId + "-v" + versionCode + "(" + versionName + ")")
}
现在我已经为跨平台 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
}
}
先进之处在于,它不会留下任何东西,并且可以将文件移动到任何需要的地方。
作为 bundle*
任务插入重命名任务。
只需将其添加到 build.gradle
文件的底部即可。
Note: It will add more tasks than necessary, but those tasks will be skipped since they don't match any folder. e.g.
> 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)
}
}
我发现了一个更好的选项,可以在您生成 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 website and this post
来自 @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。
根据 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
注意第三个参数,确保您没有使用对您来说很重要的文件夹。
编辑:为什么您可能会问 2 个命令的 .BAT。如果您在 Windows 上尝试 commandLine "copy",... 它会导致 "system does not recognize the command copy"。输入任何内容,例如 COPY、REN、RENAME 等,都不起作用。
为什么没有人为此使用现有的 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)
}
}
}
它与任何 flavors
、dimensions
和 buildTypes
完美配合。没有任何额外的任务,适用于 Toolbar -> Generate signed Bundle
中为输出设置的任何路径,可以为任何 flavor
.