news 2026/4/23 19:23:57

Flutter Android APK 重命名 签名验证操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter Android APK 重命名 签名验证操作

一、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会按顺序问你:

  1. Keystore 密码(例如:YourStorePassword

  2. 名字与姓氏 (CN):例如:

    ***
  3. 组织单位 (OU):例如:

    Development
  4. 组织名称 (O):例如:

    ****
  5. 城市或区域 (L):例如:

    ***
  6. 省/市/自治区 (ST):例如:

    ***
  7. 国家代码 (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.versionCodeflutter.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 对应关系

签名验证分两步:

  1. 验证keystore 自身信息(别名、证书 DN、指纹)

  2. 验证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 ​

核对要点:

  1. Signer #1 certificate DN是否与keytool -list输出的Owner一致

  2. 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就可以提供给需要校验证书的第三方。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 8:38:51

AlignTwoPolyDatas 基于ICP算法的配准和相机视角切换

一&#xff1a;主要的知识点 1、说明 本文只是教程内容的一小段&#xff0c;因博客字数限制&#xff0c;故进行拆分。主教程链接&#xff1a;vtk教程——逐行解析官网所有Python示例-CSDN博客 2、知识点纪要 本段代码主要涉及的有①ICP模型配准&#xff0c;②配准结果的检测…

作者头像 李华
网站建设 2026/4/23 8:38:52

YOLOv11 改进 - C2PSA | C2PSA融合EDFFN高效判别频域前馈网络(CVPR 2025):频域筛选机制增强细节感知,优化复杂场景目标检测

前言 本文介绍了高效判别频域前馈网络(EDFFN),并将其集成到YOLOv11中。EDFFN是为解决图像复原中局部信息表征不足和频域计算成本过高问题而提出的。传统方法存在SSM全局信息偏向性和频域FFN高计算成本的问题,EDFFN通过将频域操作位置从FFN中间层迁移到末端,降低了计算成本…

作者头像 李华
网站建设 2026/4/23 8:38:56

YOLOv11改进 - C3k2融合 | C3k2融DBlock解码器块( CVPR 2025 ) Decoder Block:解码器块,去模糊和提升图像清晰度

前言 本文介绍了用于多任务低光图像恢复的DarkIR模型中的DBlock,并将其集成到YOLOv11。DBlock部署在模型解码器阶段,负责图像去模糊、提升细节锐度及上采样。它遵循Metaformer架构,由扩张空间注意力模块(Di - SpAM)和门控前馈网络(GatedFFN)构成。Di - SpAM通过多尺度扩…

作者头像 李华
网站建设 2026/4/23 8:38:56

企业级应用部署中共享库问题的5个真实案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个共享库问题案例库应用&#xff0c;包含以下功能&#xff1a;1. 分类展示不同场景下的共享库错误案例&#xff08;Docker/物理机/交叉编译等&#xff09;2. 每种案例提供环境…

作者头像 李华
网站建设 2026/4/23 8:52:31

FP8:AI加速计算的新利器,如何用快马平台快速实现?

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 使用快马平台开发一个基于FP8格式的简单神经网络模型&#xff0c;用于图像分类任务。要求&#xff1a;1. 使用Kimi-K2模型生成FP8量化代码&#xff1b;2. 包含FP8数据格式转换功能&…

作者头像 李华
网站建设 2026/4/23 8:53:23

tar -czvf vs 其他压缩工具:效率对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个性能测试工具&#xff0c;对比tar -czvf、zip和rar在相同数据集下的压缩速度、压缩率和CPU占用率。工具应生成详细的对比报告&#xff0c;帮助用户选择最适合的压缩方式。点…

作者头像 李华