Flutter Android APK 重命名 & 签名验证操作
本文详细介绍了Flutter应用打包发布的全流程,主要包括:1. 生成release签名文件(keystore)的方法及参数配置;2. APK文件命名方案,在保留默认app-release.apk的同时,自动生成包含版本信息的自定义名称APK;3. 签名配置详解,包括Gradle配置和local.properties设置;4. 签名验证方法,确保APK与keystore一致;5. 常见问题解答和k
一、Flutter 打包
flutter build apk --release
二、生成 release 签名文件:autoclick-key.jks
⚠️ 此步骤只需要做 一次。已经有
autoclick-key.jks的话,可以直接跳到后面的签名配置。
2.1 生成 keystore 的命令
在项目根目录执行(确保 android/app 目录存在):
keytool -genkeypair \ -v \ -keystore ./android/app/autoclick-key.jks \ -alias autoclick \ -keyalg RSA \ -keysize 2048 \ -validity 10000
参数说明:
-
-keystore ./android/app/autoclick-key.jks生成的 keystore 文件路径与文件名(放在android/app目录下,后续 Gradle 会按这个路径去找) -
-alias autoclick此 keystore 中 key 的别名(后续local.properties和验证命令都要用同一个 alias) -
-validity 10000证书有效期天数(10000 天 ≈ 27 年,可按需调整)
2.2 生成过程中的交互说明
执行命令后,keytool 会按顺序问你:
-
Keystore 密码(例如:
YourStorePassword) -
名字与姓氏 (CN):例如:
***
-
组织单位 (OU):例如:
Development
-
组织名称 (O):例如:
****
-
城市或区域 (L):例如:
***
-
省/市/自治区 (ST):例如:
***
-
国家代码 (C):例如:
CN
最后会给出一行类似:
CN=****, OU=Development, O=****, L=jinan, ST=shandong, C=CN 是否正确? [否]:
这里输入:
y
或 yes 即可完成生成。
2.3 生成后的文件位置与备份
生成成功后:
-
文件路径:
android/app/autoclick-key.jks -
这个文件 非常重要:
-
以后所有版本更新 必须使用同一个 keystore 签名
-
丢失后将无法给已安装用户推送升级
-
建议:
-
备份到安全位置(例如移动硬盘 / 私有云盘)
-
记录:
-
keystore 文件名:
autoclick-key.jks -
keystore 密码:
storePassword -
alias:
autoclick -
key 密码:
keyPassword(若与 keystore 密码不同)
-
三、APK 文件名修改方案说明
3.1 核心目标
在保持 Flutter 默认生成的:
-
app-release.apk
的同时,额外复制一份带有应用名 + 版本号的 APK:
-
autoclick-v1.0.0(1)-release.apk(示例)
这样既不影响 Flutter 工具寻找默认 APK,又方便对外发布。
3.2 版本号来源:local.properties
在 build.gradle.kts 中,通过 local.properties 获取 Flutter 写入的版本信息:
// 1️⃣ 从 local.properties 中读取 Flutter 写入的版本号
val localProperties = Properties().apply {
val localPropsFile = rootProject.file("local.properties")
if (localPropsFile.exists()) {
load(FileInputStream(localPropsFile))
}
}
// 如果没取到,就给个默认值防止构建失败
val flutterVersionCode: Int =
(localProperties.getProperty("flutter.versionCode") ?: "1").toInt()
val flutterVersionName: String =
localProperties.getProperty("flutter.versionName") ?: "1.0.0"
Flutter 在运行
flutter build时会自动往local.properties写入flutter.versionCode、flutter.versionName,这里直接读出来用于 APK 命名。
3.3 自定义拷贝 & 重命名 Release APK
在 android/app/build.gradle.kts 底部定义任务:
// === 重命名 flutter-apk 产物:Release 版本 ===
tasks.register("copyAndRenameFlutterApkRelease") {
doLast {
val outputDir = file("$buildDir/outputs/flutter-apk")
if (!outputDir.exists()) {
println("flutter-apk dir not found, skip rename (release)")
return@doLast
}
val appName = "autoclick"
val vName = flutterVersionName
val vCode = flutterVersionCode
outputDir.listFiles()?.forEach { file ->
if (file.isFile && file.extension == "apk" && "release" in file.name) {
val newName = "${appName}-v${vName}(${vCode})-release.apk"
val newFile = File(outputDir, newName)
// ✅ 注意:copy 而不是 rename,保留原始 app-release.apk
file.copyTo(newFile, overwrite = true)
println("Copied and renamed flutter-apk → $newName")
}
}
}
}
关键点说明:
-
遍历
build/outputs/flutter-apk下的所有.apk文件 -
只处理文件名中包含
release的 APK -
新文件命名规则:
${appName}-v${versionName}(${versionCode})-release.apk 例:autoclick-v1.0.0(1)-release.apk -
使用
copyTo(),保证 原始app-release.apk不被删除,Flutter 仍然能找到默认 APK
3.4 与 assembleRelease 任务关联
为了在每次构建 Release APK 时自动执行上述复制任务:
// ✅ 用 matching 动态关联 assembleRelease 任务,避免 “Task not found” 错误
tasks.matching { it.name == "assembleRelease" }.configureEach {
finalizedBy("copyAndRenameFlutterApkRelease")
}
含义:
-
在 Gradle 中匹配名为
assembleRelease的任务 -
为其追加
finalizedBy("copyAndRenameFlutterApkRelease") -
即:
assembleRelease执行完成后,自动执行拷贝重命名任务
3.5 打包后目录结构示例
执行:
flutter build apk --release
成功后,build/app/outputs/flutter-apk/ 目录中会同时存在:
app-release.apk # Flutter 默认产物 autoclick-v1.0.0(1)-release.apk # 自定义命名产物(用于发布)
对外发包 / 安装测试时推荐使用:
autoclick-v1.0.0(1)-release.apk
四、签名配置说明(signingConfigs + local.properties)
4.1 Gradle 中的签名配置
在 android { signingConfigs { ... } } 中:
signingConfigs {
create("release") {
// 这里从 local.properties 中读取参数,这里有个 app/,
// 所以 keytool 生成的 jks 要放到 android/app 目录下
storeFile = localProperties.getProperty("storeFile")
?.let { File(rootProject.projectDir, "app/$it") }
storePassword = localProperties.getProperty("storePassword")
keyAlias = localProperties.getProperty("keyAlias")
keyPassword = localProperties.getProperty("keyPassword")
}
}
在 buildTypes 中启用 release 签名:
buildTypes {
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
// 使用上面的 release 签名配置
signingConfig = signingConfigs.getByName("release")
// 只需要手动创建 proguard-rules.pro,可以是空文件,但要放在 app 目录下
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
getByName("debug") {
isMinifyEnabled = false
isShrinkResources = false
}
}
4.2 local.properties 中的签名字段示例
在 android/local.properties 中,新增(敏感信息请自己替换):
# keystore 文件名(相对 android/app 路径) storeFile=autoclick-key.jks # keystore 密码 storePassword=你的_keystore_密码 # key 别名(alias),例如:autoclick keyAlias=autoclick # key 密码(通常与 storePassword 相同,也可以不同) keyPassword=你的_key_密码
⚠️ 注意:
autoclick-key.jks文件应位于:android/app/autoclick-key.jks请勿将包含密码的
local.properties和.jks文件提交到公共仓库(如 GitHub 公共仓库)
五、签名验证:keystore 与 APK 对应关系
签名验证分两步:
-
验证 keystore 自身信息(别名、证书 DN、指纹)
-
验证 APK 使用的签名证书,确认与 keystore 一致
5.1 查看 keystore 证书信息(keytool)
在项目根目录执行(或调整路径到实际位置):
keytool -list -v -keystore ./android/app/autoclick-key.jks -alias autoclick
命令说明:
-
-keystore:指向你的 keystore 文件 -
-alias:你生成 keystore 时设置的别名(这里是autoclick)
执行后会让你输入 keystore 密码,成功后会输出类似:
Alias name: autoclick Creation date: ... Entry type: PrivateKeyEntry Owner: CN=***, OU=Development, O=***, L=****, ST=****, C=CN SHA1: AA:BB:CC:DD:... SHA256: 11:22:33:44:... ...
建议记录下:
-
Owner(证书 DN) -
SHA1 -
SHA256
后续与 APK 对比使用。
5.2 验证 Release APK 的签名证书(apksigner)
使用你自定义命名的 Release APK 文件:
apksigner verify --print-certs \ build/app/outputs/flutter-apk/autoclick-v1.0.0(1)-release.apk
如果系统找不到
apksigner,可以使用 Android SDK 中的完整路径,例如:$ANDROID_HOME/build-tools/<build-tools-version>/apksigner verify --print-certs \ build/app/outputs/flutter-apk/autoclick-v1.0.0(1)-release.apk
输出示例:
Verifies Verified using v2 scheme (APK Signature Scheme v2) Verified using v3 scheme (APK Signature Scheme v3) Number of signers: 1
核对要点:
-
Signer #1 certificate DN是否与keytool -list输出的Owner一致 -
SHA-1 digest/SHA-256 digest是否与 keystore 中的SHA1/SHA256一致
如果两处信息完全一致,说明:
✅
autoclick-v1.0.0(1)-release.apk确实是用android/app/autoclick-key.jks中 alias 为autoclick的 key 进行签名的,可以作为正式 Release 包对外发布。
六、常见问题 FAQ
Q1:目录里有两个 APK,我到底用哪个?
-
app-release.apk-
Flutter 默认生成,工具链依赖它
-
-
autoclick-v1.0.0(1)-release.apk-
通过
copyAndRenameFlutterApkRelease任务生成 -
推荐作为 对外发布 / 安装测试 / 上架 的文件
-
签名一致,用哪一个都行;建议统一使用自定义命名的那个。
Q2:每次改版本号,需要改哪里?
-
Flutter 侧:在
pubspec.yaml中修改:version: 1.0.0+1
-
1.0.0=flutter.versionName -
1=flutter.versionCode
-
-
执行构建命令时,Flutter 会自动同步到
local.properties, Gradle 的flutterVersionName/flutterVersionCode会自动更新, 自定义 APK 命名也会随之变化,无需额外修改代码。
Q3:如何确认当前 Release 是否用的是 debug 签名?
如果 apksigner 输出中出现类似:
CN=Android Debug, O=Android, C=US
则说明是 debug 签名,需要检查:
-
buildTypes { release { signingConfig = signingConfigs.getByName("release") } }是否正确 -
local.properties中的storeFile等字段是否填写完整 -
keystore 路径是否存在、密码是否正确
七、keytool 常用操作速查(进阶)
本节是对 keytool 相关操作的补充,方便以后查看 / 维护 keystore。 生成 keystore 的命令已在 第二章 给出,这里不再重复。
7.1 查看 keystore 中所有别名(alias 列表)
如果忘记 keystore 中有哪些 alias,可以不加 -alias,只看列表:
keytool -list -keystore ./android/app/autoclick-key.jks
系统会让你输入 keystore 密码,然后打印所有别名名称。 再根据别名,使用前面的:
keytool -list -v -keystore ./android/app/autoclick-key.jks -alias autoclick
查看某个具体 alias 的详细证书信息。
7.2 修改 keystore 密码 / key 密码(可选操作)
修改 keystore 密码:
keytool -storepasswd -keystore ./android/app/autoclick-key.jks
修改某个 alias 对应的 key 密码:
keytool -keypasswd \ -keystore ./android/app/autoclick-key.jks \ -alias autoclick
修改后记得同步更新 android/local.properties 中的:
storePassword=新的_keystore_密码 keyPassword=新的_key_密码
7.3 导出证书(可用于对接第三方平台)
部分第三方平台会要求你提供签名证书(.cer / .pem):
keytool -exportcert \ -keystore ./android/app/autoclick-key.jks \ -alias autoclick \ -file ./android/app/autoclick-cert.cer \ -rfc
生成的 autoclick-cert.cer 就可以提供给需要校验证书的第三方。
更多推荐


所有评论(0)