一、前提说明(Flutter 项目通用)
1.1 APK 默认生成位置与名称
执行:
flutter build apk --debug flutter build apk --release
最终会在:
build/app/outputs/flutter-apk/
看到:
app-debug.apk app-release.apk
1.2 Flutter 版本号从哪里来?
在pubspec.yaml:
version: 1.0.0+1
含义:
1.0.0→ versionName1→ versionCode
Flutter 会将版本写入:
local.properties flutter.versionName=1.0.0 flutter.versionCode=1
Gradle 即可读取使用。
二、Flutter 构建目录说明:apk 与 flutter-apk 的区别
2.1 apk/ 目录说明(非最终产物)
示例:
build/app/outputs/apk/release/app-release.apk
📌这是 Android 原生构建结果,不是 Flutter 最终包。
Flutter 会继续对其加工,所以不能作为发布包。
2.2 flutter-apk/ 目录说明(最终产物)
示例:
build/app/outputs/flutter-apk/app-release.apk
📌这是 Flutter 最终要交付给用户 / 商店的 APK。你上传应用商店的就是这个文件。
2.3 两者关系图示
Android Gradle assemble → 生成 outputs/apk/ 原始 APK Flutter Toolchain 再处理 → 生成 outputs/flutter-apk/ 最终 APK(必须使用)
三、Groovy 版 APK 改名方法(旧项目)
(如果你的文件是build.gradle)
applicationVariants.all { variant -> variant.outputs.all { output -> def appName = "autoclick" def versionName = variant.versionName def versionCode = variant.versionCode outputFileName = "${appName}-v${versionName}(${versionCode})-${variant.name}.apk" } }⚠只修改 apk/,不会影响 flutter-apk。
四、Kotlin DSL(build.gradle.kts)APK 改名方法(你当前使用)
4.1 基础版(只能改 apk/,不能改 flutter-apk/)
applicationVariants.all { val variantName = name val vName = versionName val vCode = versionCode val appName = "autoclick" outputs.all { val outputImpl = this as com.android.build.gradle.internal.api.BaseVariantOutputImpl outputImpl.outputFileName = "${appName}-v${vName}(${vCode})-${variantName}.apk" } }⚠ Flutter 最终产物不会被修改!
4.2 Kotlin DSL 关键解释
不能使用
def(必须val/var)outputs类型是接口 → 必须强转BaseVariantOutputImpl才能改名不会影响 flutter-apk!
五、🔥 高阶玩法(唯一能修改 flutter-apk 的方式)
Flutter 3.x 的最终 APK 不再由 applicationVariants 管理 👉必须使用 Gradle Task Hook 才能改名。
5.1 读取 Flutter 版本号
val localProperties = Properties().apply { val file = rootProject.file("local.properties") if (file.exists()) load(FileInputStream(file)) } val flutterVersionName = localProperties.getProperty("flutter.versionName") ?: "1.0.0" val flutterVersionCode = localProperties.getProperty("flutter.versionCode")?.toInt() ?: 15.2 同步 Android 版本号
android { defaultConfig { versionName = flutterVersionName versionCode = flutterVersionCode } }5.3 重命名 flutter-apk 最终产物(核心!)
tasks.whenTaskAdded { if (name.startsWith("assemble")) { doLast { val outputDir = file("$buildDir/outputs/flutter-apk") if (!outputDir.exists()) return@doLast val appName = "autoclick" val files = outputDir.listFiles() ?: return@doLast files.forEach { file -> if (file.extension == "apk") { val variant = when { "release" in file.name -> "release" "debug" in file.name -> "debug" else -> "unknown" } val newName = "${appName}-v${flutterVersionName}(${flutterVersionCode})-${variant}.apk" file.renameTo(File(outputDir, newName)) println("flutter-apk renamed → $newName") } } } } }六、构建验证流程
flutter clean flutter build apk --release
查看:
build/app/outputs/flutter-apk/
你会看到:
autoclick-v1.0.0(1)-release.apk
七、为什么最终必须使用 flutter-apk?(机制解析)
因为 Flutter 执行以下流程:
1. Gradle assemble → 在 outputs/apk 生成原生 APK 2. Flutter toolchain 二次加工 → 在 outputs/flutter-apk 输出最终 APK
原生 APK无法直接使用,Flutter 会:
重写资源
合并 Flutter 引擎构建产物
压缩优化
写入 Meta-info
根据 Flutter 配置重新签名
👉因此 flutter-apk 必须使用,apk 不可用。
八、自定义命名格式(可扩展)
你可以定制:
✔ 时间戳
autoclick-v1.0.0(1)-20250207-release.apk
✔ 渠道(小米 / 华为 / oppo)
autoclick-xiaomi-v1.0.0-release.apk
✔ CPU 架构
autoclick-arm64-v1.0.0-release.apk
我可以根据你的规范生成完整模板。