Flutter 打包 / 发布签名完整指南
Bundle ID 示例统一使用
com.example.aioli本文档涵盖 Android Keystore、iOS 证书、Provisioning Profile、App Store Connect API Key 的完整生成与配置流程。
目录
- Android 签名(Keystore)
- iOS 证书(Distribution Certificate)
- iOS Provisioning Profile
- App Store Connect API Key
- 第三方平台签名(极光等)
- CI/CD GitHub Secrets 汇总
- Flutter 项目关联配置
一、Android 签名(Keystore)
1.1 生成 Keystore 文件
前提:已安装 JDK(Android Studio 自带,或
brew install --cask temurin)
keytool -genkey -v \
-keystore orion_release.jks \
-alias orion_key \
-keyalg RSA \
-keysize 2048 \
-validity 10000
交互填写示例:
Enter keystore password: ← 设置 storePassword(记住!)
Re-enter new password: ← 再次确认
What is your first and last name? Aioli Team
What is the name of your org unit? Mobile
What is the name of your organization? Aioli
What is the name of your City? Taipei
What is the name of your State? Taiwan
What is the two-letter country code? TW
Is CN=Aioli Team, ... correct? [no]: yes
Enter key password for <orion_key>: ← 设置 keyPassword(可直接回车=同上)
生成文件:orion_release.jks(当前目录)
1.2 验证 Keystore
keytool -list -v \
-keystore orion_release.jks \
-alias orion_key
输出关键信息:
Alias name: orion_key
Certificate fingerprints:
MD5: BA:CC:E1:2F:... ← 32字节,去冒号后32字符
SHA1: AA:BB:CC:DD:... ← 20字节,去冒号后40字符
SHA256: EE:FF:00:11:... ← 32字节,去冒号后64字符
1.3 查看各格式签名指纹
# 查看 keystore 签名
keytool -list -v -keystore orion_release.jks -alias orion_key -storepass 你的密码
# 查看已构建 APK 的签名
apksigner verify --print-certs build/app/outputs/flutter-apk/app-release.apk
# 验证 APK 与 keystore 签名一致(SHA256 对比)
keytool -list -v -keystore orion_release.jks -alias orion_key -storepass 你的密码 \
| grep SHA256 | tr '[:lower:]' '[:upper:]'
apksigner verify --print-certs build/app/outputs/flutter-apk/app-release.apk \
| grep "SHA-256" | tr '[:lower:]' '[:upper:]'
1.4 生成各平台所需格式
# MD5(32字符)← 极光推送、微信开放平台等
keytool -exportcert \
-keystore orion_release.jks \
-alias orion_key \
-storepass 你的密码 \
| md5sum | awk '{print $1}'
# SHA1(40字符)← 高德地图、百度地图、Firebase
keytool -list -v -keystore orion_release.jks -alias orion_key -storepass 你的密码 \
| grep "SHA1:" | awk '{print $2}' | tr -d ':'
# SHA256(64字符)← Google Play Console
keytool -list -v -keystore orion_release.jks -alias orion_key -storepass 你的密码 \
| grep "SHA256:" | awk '{print $2}' | tr -d ':'
各平台签名格式速查:
| 平台 | 格式 | 字符数 |
|---|---|---|
| Google Play Console | SHA256,去冒号 | 64 |
| 极光推送 / 一键登录 | MD5,去冒号,小写 | 32 |
| 微信开放平台 | MD5,去冒号,小写 | 32 |
| 高德 / 百度地图 | SHA1,去冒号 | 40 |
| Firebase | SHA1 或 SHA256 | 40 / 64 |
1.5 转 base64(用于 CI)
# macOS(直接复制到剪贴板)
base64 -i orion_release.jks | pbcopy
base64 -w0 -i orion_release.jks | pbcopy
# Linux
base64 -w 0 orion_release.jks > keystore_base64.txt
1.6 签名注意事项
orion_release.jks是 Android 发布生命周期中最重要的文件- 上传第一个版本到 Google Play 后,签名永久绑定,丢失无法更换
- 原始文件备份到公司密码管理器(1Password / Bitwarden),不要提交到 Git
.gitignore中添加:*.jks、*.keystore、key.properties
二、iOS 证书(Distribution Certificate)
前提:已有 Apple Developer 账号(99$/年),当前 Mac 将持有私钥
2.1 生成 CSR(证书签名请求)
打开 Keychain Access(钥匙串访问)
菜单栏 → Keychain Access
→ Certificate Assistant(证书助理)
→ Request a Certificate From a Certificate Authority(从证书颁发机构请求证书)
填写:
- User Email:Apple ID 邮箱
- Common Name:任意,如 Aioli Distribution
- CA Email:留空
- 选择 Saved to disk(存储到磁盘)
保存生成 CertificateSigningRequest.certSigningRequest,同时私钥自动存入当前 Mac 的 Keychain。
2.2 在 Apple Developer 后台创建证书
登录 developer.apple.com/account/resources/certificates
点击 + → 选择 Apple Distribution → 上传 .certSigningRequest 文件 → 下载 .cer 文件
2.3 导入证书到 Keychain
# 双击 .cer 文件自动导入,或命令行:
security import ~/Downloads/distribution.cer \
-k ~/Library/Keychains/login.keychain-db
2.4 导出 .p12 文件
打开 Keychain Access → 搜索 Apple Distribution
⚠️ 必须在生成 CSR 的那台 Mac 上操作,证书左侧有展开箭头(含私钥)才能导出 .p12
右键证书 → 导出(Export)
格式选择 .p12
设置导出密码(即 IOS_DISTRIBUTION_CERT_PASSWORD)
转 base64:
base64 -i Distribution.p12 | pbcopy
2.5 .p12 灰色无法选择的解决方法
原因:当前 Mac 上只有证书,没有对应私钥。
有私钥(可导出): 没有私钥(.p12灰色):
▼ 🏅 Apple Distribution: xxx 🏅 Apple Distribution: xxx
🔑 私钥 (无法展开)
解决方案:
方案 A:去原来生成 CSR 的 Mac 上,同时选中证书和私钥(Cmd 多选)→ 右键导出
方案 B:在当前 Mac 重新生成 CSR → Apple Developer 后台吊销旧证书 → 用新 CSR 申请新证书 → 导入 → 导出 .p12
注意:吊销旧证书后,用旧证书签名的 Provisioning Profile 会失效,需重新生成 PP。已安装在用户设备上的 App 不受影响。
三、iOS Provisioning Profile
3.1 确认 Bundle ID(App Identifier)
登录 developer.apple.com/account/resources/identifiers
若不存在,点击 + 创建:
- 类型:App IDs
- Bundle ID 模式:Explicit
- Bundle ID:com.example.aioli(生产)/ com.example.aioli.dev(开发,可选)
3.2 创建 Dev Provisioning Profile
登录 developer.apple.com/account/resources/profiles
点击 +:
类型:iOS App Development
Bundle ID:com.example.aioli.dev(或 com.example.aioli)
Certificate:选择刚才创建的 Distribution 证书
Devices:选择测试设备
Name:Aioli Dev Profile
下载 Aioli_Dev_Profile.mobileprovision,转 base64:
base64 -i "Aioli_Dev_Profile.mobileprovision" | pbcopy
3.3 创建 Prod Provisioning Profile
类型:App Store Connect
Bundle ID:com.example.aioli
Certificate:选择 Distribution 证书
Name:Aioli AppStore Profile
下载 Aioli_AppStore_Profile.mobileprovision,转 base64:
base64 -i "Aioli_AppStore_Profile.mobileprovision" | pbcopy
3.4 查看 PP 详细信息
# 查看 PP 的 UUID、有效期、Bundle ID
security cms -D -i "Aioli_Dev_Profile.mobileprovision" \
| grep -A1 "UUID\|application-identifier\|ExpirationDate"
四、App Store Connect API Key
用于 CI 自动上传 IPA,比账号密码更安全。
4.1 生成 API Key
左上角用户头像 → Integrations → App Store Connect API → 点击 +
Name:CI Deploy Key
Access:App Manager
4.2 记录三个关键值
| 值 | 位置 | 对应 Secret |
|---|---|---|
| Key ID | Key 列表中,格式 AB12CD34EF |
APP_STORE_CONNECT_KEY_ID |
| Issuer ID | 页面顶部,UUID 格式 | APP_STORE_CONNECT_ISSUER_ID |
| .p8 私钥文件 | 点 Download API Key 下载 | APP_STORE_CONNECT_KEY_BASE64 |
转 base64:
base64 -i AuthKey_XXXXXXXXXX.p8 | pbcopy
⚠️
.p8文件只能下载一次,请立即备份到密码管理器。
五、第三方平台签名(极光等)
5.1 极光推送 / 一键登录(Android)
需要 MD5 格式签名(32字符小写):
keytool -exportcert \
-keystore orion_release.jks \
-alias orion_key \
-storepass 你的密码 \
| md5sum | awk '{print $1}'
# 输出示例:bacce12f3a445b6c7d8e9fa0b1c2d3e4
填入极光控制台:应用管理 → Android → 应用签名 MD5
5.2 极光推送(iOS)
iOS 端需上传 APNs 证书,在 Apple Developer 后台创建:
Certificates → + → Apple Push Notification service SSL (Sandbox & Production)
→ 选择 Bundle ID:com.example.aioli
→ 上传 CSR → 下载 .cer → 导入 Keychain → 导出 .p12
将 .p12 上传到极光控制台 → iOS → APNs 证书
六、CI/CD GitHub Secrets 汇总
进入仓库 → Settings → Secrets and variables → Actions → New repository secret
Android
| Secret 名称 | 值来源 | 备注 |
|---|---|---|
ANDROID_KEYSTORE_BASE64 |
base64 -i orion_release.jks |
jks 文件的 base64 |
ANDROID_STORE_PASSWORD |
keytool 设置的 storePassword | |
ANDROID_KEY_PASSWORD |
keytool 设置的 keyPassword | |
ANDROID_KEY_ALIAS |
-alias 值,如 orion_key |
iOS 证书
| Secret 名称 | 值来源 | 备注 |
|---|---|---|
IOS_DISTRIBUTION_CERT_BASE64 |
base64 -i Distribution.p12 |
|
IOS_DISTRIBUTION_CERT_PASSWORD |
导出 .p12 时设置的密码 | |
IOS_DEV_PROVISIONING_PROFILE_BASE64 |
Dev PP 的 base64 | |
IOS_PROD_PROVISIONING_PROFILE_BASE64 |
Prod PP 的 base64 | |
IOS_DEV_PROFILE_NAME |
如 Aioli Dev Profile |
与 PP 创建时名称一致 |
IOS_PROD_PROFILE_NAME |
如 Aioli AppStore Profile |
|
IOS_DEV_BUNDLE_ID |
com.example.aioli.dev |
|
IOS_PROD_BUNDLE_ID |
com.example.aioli |
|
APPLE_TEAM_ID |
developer.apple.com → Membership | 格式如 A1B2C3D4E5 |
App Store Connect API
| Secret 名称 | 值来源 | 备注 |
|---|---|---|
APP_STORE_CONNECT_KEY_ID |
API Key 列表中 | 格式如 AB12CD34EF |
APP_STORE_CONNECT_ISSUER_ID |
页面顶部 | UUID 格式 |
APP_STORE_CONNECT_KEY_BASE64 |
base64 -i AuthKey_xxx.p8 |
只能下载一次 |
已有(OSS + GitHub)
| Secret 名称 | 备注 |
|---|---|
GH_PAT |
有写权限的 Personal Access Token |
OSS_ENDPOINT |
阿里云 OSS endpoint |
OSS_ACCESS_KEY_ID |
OSS AccessKey ID |
OSS_ACCESS_KEY_SECRET |
OSS AccessKey Secret |
OSS_BUCKET |
OSS Bucket 名称 |
七、Flutter 项目关联配置
7.1 Android:android/key.properties(本地开发)
storeFile=../../orion_release.jks
storePassword=你的密码
keyAlias=orion_key
keyPassword=你的密码
7.2 Android:android/app/build.gradle.kts
import java.util.Properties
import java.io.FileInputStream
val keyPropsFile = rootProject.file("key.properties")
val keyProps = Properties()
if (keyPropsFile.exists()) {
keyProps.load(FileInputStream(keyPropsFile))
}
android {
signingConfigs {
create("release") {
val storeFilePath = keyProps["storeFile"] as String?
if (storeFilePath != null) storeFile = file(storeFilePath)
storePassword = keyProps["storePassword"] as String?
keyAlias = keyProps["keyAlias"] as String?
keyPassword = keyProps["keyPassword"] as String?
}
}
buildTypes {
getByName("release") {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
}
}
}
7.3 .gitignore(必须添加)
# Android 签名(根目录)
*.jks
*.keystore
android/key.properties
# iOS 证书
*.p12
*.mobileprovision
ios/ExportOptions.plist
7.4 本地构建验证
# Android
flutter build apk --release
apksigner verify --print-certs build/app/outputs/flutter-apk/app-release.apk | grep SHA-256
# iOS
flutter build ipa --release --export-options-plist=ios/ExportOptions.plist
附:各文件备份清单
| 文件 | 存放位置 | 重要程度 |
|---|---|---|
orion_release.jks |
公司密码管理器 | ⭐⭐⭐⭐⭐ 丢失无法恢复 |
Distribution.p12 |
公司密码管理器 | ⭐⭐⭐⭐ 可重新生成但麻烦 |
AuthKey_xxx.p8 |
公司密码管理器 | ⭐⭐⭐⭐ 只能下载一次 |
*.mobileprovision |
可随时从 Apple 后台重新下载 | ⭐⭐ |
key.properties |
本地,不提交 Git | ⭐⭐⭐ |
Page Source