在 AGP 8+ 及 9.0 中修改构建 APK 名称的方法

73 阅读1分钟

​不小心把项目升到AGP 9.0了,然后一看applicationVariants.all找不到了,看Android官方文档说被androidComponents替换了,换完发现怎么outputs也找不到了,下面的示例又绝口不提怎么修改apk名称,可给我一顿找啊,期间还找到有人提过issues:Renaming APK using new AGP DSL(里面回复这个答案的人也是我),都一个多月了谷歌也没有回复,好嘛,还得我自己来。经过我几天的研究,终于找到了方法(谷歌你坏事做尽啊)

旧版本方法 (AGP 7.0 及更早)

我们都知道,在 AGP 8.0 版本之前,通常通过 applicationVariantsAPI 在 android代码块内进行操作:

android {
    ...
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            outputFileName = "你的应用名_V${variant.versionName}_Build${variant.versionCode}_${variant.buildType.name}.apk"
        }
    }
}

注意:从 AGP 8.0 开始,上述 API 已被废弃。下面的方法是适用于新版本 AGP (8.0+) 的解决方案。

新版本方法 (AGP 8.0+ 及 9.0 DSL)

从 AGP 8.0 开始,官方引入了新的变体 API (androidComponents),并在 AGP 9.0 中进一步优化。以下方法适用于 AGP 8.0 及以上版本。

场景一:仅重命名 APK(不改变输出位置)

如果只需要修改生成的 APK 文件的名称,可以使用以下相对简单的方法:

app/build.gradle.kts

// 放在最外层,不要放android块里
androidComponents {
    onVariants { variant ->
        variant.outputs.forEach { output ->
            val apkName = "你的应用名_V${output.versionName.get()}_Build${output.versionCode.get()}_${variant.buildType}.apk"
            (output as VariantOutputImpl).outputFileName = apkName
        }
    }
}

场景二:重命名并移动 APK 文件

如果你在重命名后还需要将 APK 文件移动到其他目录,则需要更复杂的逻辑,在构建任务完成后执行文件操作:

app/build.gradle.kts

import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

// 放在最外层,不要放android块里
androidComponents {
    onVariants { variant ->
        variant.outputs.forEach { output ->
            val out = output as VariantOutputImpl
            // 等待项目配置完成后,再挂钩任务
            afterEvaluate {
                val capitalizedVariantName = variant.name.replaceFirstChar { it.uppercase() }
                tasks.named("assemble${capitalizedVariantName}") {
                    doLast {
                        // 默认的 APK 输出目录
                        val apkFolder = Paths.get(
                            variant.artifacts.get(
                                com.android.build.api.artifact.SingleArtifact.APK
                            ).get().toString()
                        )
                        // 构建原始文件路径和新文件路径
                        val apkPath = apkFolder.resolve(out.outputFileName.get())
                        val newApkName = "你的应用名_V${out.versionName.get()}_Build${out.versionCode.get()}_${variant.name}.apk"
                        // 我这里仅做复制处理,你也可在此处指定完全不同的目录
                        val newApkPath = apkFolder.resolve(newApkName)
                        Files.move(apkPath, newApkPath, StandardCopyOption.REPLACE_EXISTING)
                    }
                }
            }
        }
    }
}