Step 1:生成 keystore 签名文件#
在项目根目录执行 keytool 生成上传密钥,输出到 android/app/upload-keystore.jks:
keytool -genkey -v \
-keystore android/app/upload-keystore.jks \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-alias upload \
-dname "CN=OvoGame, OU=Dev, O=OvoGame, L=Beijing, ST=Beijing, C=CN"由于 -dname 已经把身份信息(CN、O、L 等)通过命令行直接传入,keytool 只会询问密码:
Enter keystore password: ← 输入 keystore 密码(自己设一个,务必记住)
Re-enter new password: ← 再输一次确认
Enter key password for <upload>:
(RETURN if same as keystore password): ← 直接回车,表示与 keystore 密码相同
-dname中的公司/地区信息和-alias(别名,后续key.properties要用到)都可以按需修改,但要保证三处配置里的别名一致。
Step 2:创建 key.properties#
这个文件的作用是把 keystore 的密码告诉 Gradle,这样打包时能自动完成签名。它包含明文密码,不能提交到 git——好在 Flutter 默认的 android/.gitignore 里已经包含了 key.properties(以及 **/*.jks)这两条规则,密钥文件天然安全。
在 android/ 目录下创建 key.properties,内容如下(替换为你的实际密码):
storePassword=********
keyPassword=********
keyAlias=upload
storeFile=upload-keystore.jks| 字段 | 含义 |
|---|---|
storePassword | keystore 文件的密码 |
keyPassword | 别名为 upload 的密钥密码(上一步若直接回车,则与 storePassword 相同) |
keyAlias | 生成 keystore 时指定的 -alias,必须一致 |
storeFile | keystore 文件路径,相对 android/app/ 解析 |
Step 3:配置 build.gradle.kts 启用 release 签名#
打开 android/app/build.gradle.kts,做三处修改。
① 在文件顶部引入签名所需的两个类:
import java.util.Properties
import java.io.FileInputStream② 在 plugins {} 与 android {} 之间插入加载 key.properties 的逻辑:
// 从 android/key.properties 读取上传密钥凭据
// key.properties 已被 git 忽略,签名密钥不会进入版本控制
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}③ 在 android {} 中新增 signingConfigs,并让 release 构建类型使用它。 完整的 android {} 配置如下:
android {
namespace = "com.ovogame.app"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it as String) }
storePassword = keystoreProperties["storePassword"] as String?
}
}
defaultConfig {
// TODO: Specify your own unique Application ID
applicationId = "com.ovogame.app"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// 用 upload keystore (key.properties) 签名 release 构建
signingConfig = signingConfigs.getByName("release")
}
}
}
namespace和applicationId要改成你自己的包名(如com.yourcompany.yourapp),三个值需保持一致。⚠️ 包名一旦上传过 Google Play 就永久锁定、不可更改。改包名只在「从未上架」时可行,否则会被识别成一个全新的应用。
Step 4:打包发布包#
更新版本号#
发版前先确认 pubspec.yaml 中的版本号:
version: 1.0.0+1
# ↑ ↑
# versionName versionCodeversionName(1.0.0):用户可见的版本号versionCode(1):整数,每次发版必须递增(1→2→3),Google Play 据此判断新旧版本,上传时必须大于上一次
例如版本号演进:1.0.0+1 → 1.0.1+2 → 1.1.0+3。
执行打包命令#
签名配置完成后,执行构建命令生成发布包。Google Play 要求使用 AAB 格式:
flutter build appbundle --release产物位于 build/app/outputs/bundle/release/app-release.aab。
遇到缓存导致的异常时,可先
flutter clean && flutter pub get清理旧产物再重新打包。
AAB 与 APK 的区别:
| 格式 | 命令 | 产物路径 | 用途 | 上架 Google Play |
|---|---|---|---|---|
| AAB (.aab) | flutter build appbundle --release | build/app/outputs/bundle/release/app-release.aab | 官方推荐格式,按用户设备生成优化后的 APK | ✅ 必需 |
| APK (.apk) | flutter build apk --release | build/app/outputs/flutter-apk/app-release.apk | 自行分发(官网下载、第三方商店、真机测试) | ❌ 2021 年起不再接受 |
Step 5:验证产物#
打完包别急着上传,先确认签名正确、能在真机运行。
真机安装测试#
AAB 无法直接安装,先打一个 APK 用于真机验证:
flutter build apk --release
adb install build/app/outputs/flutter-apk/app-release.apk确认能正常打开、WebView 加载正常、网络权限 OK。
验证签名#
确认 release 包用的是你的 upload keystore、而非 debug 签名——对比 keystore 与 APK 的 SHA-256 指纹:
# keystore 的指纹
keytool -list -v -keystore android/app/upload-keystore.jks -alias upload -storepass <密码> | grep SHA256
# APK 实际签名指纹(需 Android SDK build-tools 的 apksigner)
apksigner verify --print-certs build/app/outputs/flutter-apk/app-release.apk | grep SHA-256两个指纹一致,即证明发布包由你的上传密钥签名。
总结#
整个上架前的签名配置流程可归纳为四步:
- 用
keytool生成upload-keystore.jks - 在
android/key.properties写入密钥凭据 - 修改
build.gradle.kts,让release构建自动签名 flutter build appbundle产出 AAB,上传到 Play Console
上传到 Google Play#
拿到 app-release.aab 后,登录 Google Play Console 创建应用,依次完成商品详情填写、内容分级问卷与隐私政策,再上传 AAB 提交审核。几个关键点:
- 首次需创建开发者账号,一次性费用 $25
- 上传的必须是
.aab,而非 APK - 每次上传的
versionCode必须大于上一次 - 首次审核约 1-3 天,后续更新通常数小时
常见问题#
Q:提示找不到 keytool / apksigner?
直接用 Android Studio 自带的工具:
keytool:C:\Program Files\Android\Android Studio\jbr\bin\apksigner:<Android SDK>\build-tools\<版本>\(SDK 路径见android/local.properties的sdk.dir)
Q:打包失败提示签名相关错误?
依次检查:android/key.properties 是否存在且四项齐全;密码、alias 是否与创建 keystore 时一致;storeFile 路径相对 android/app/ 解析。
Q:构建很慢,或日志里有 tree-shaken 字样?
首次构建需下载并编译依赖,耗时几分钟正常,后续有缓存会快很多;遇到缓存异常时 flutter clean 后重试。构建日志中的 MaterialIcons-Regular.otf was tree-shaken 是正常优化(字体从 1.6MB 降到约 1KB),无需处理。
