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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐