一、问题背景
使用 Tauri 构建 Android 应用时,本地打包的 APK 与 Google Play 商店最终分发的版本签名不一致,导致:
- 本地 APK 无法直接覆盖 Play 商店安装的版本
- 从其他渠道下载的 APK 也无法被 Play 商店正常更新
根本原因是 Play App Signing 机制:
| 密钥类型 | 持有者 | 用途 |
|---|---|---|
| Upload Key(上传密钥) | 开发者本地 | 签名上传到 Play Console 的 AAB |
| App Signing Key(应用签名密钥) | Google 托管 | 最终给用户下载的 APK 签名 |
本地用 Upload Key 签名的 APK,与商店版签名必然不同。
二、正确的自动化目标
目标不是让本地 Tauri 打出的 APK 和商店版签名一致(几乎不可能,因为没有 App Signing Key 私钥),而是:
- 用 Upload Key 签名 AAB 并上传到 Play Console
- 让 Google 用 App Signing Key 生成最终 APK
- 通过 API 下载这份已用 App Signing Key 签名的 Universal APK
- 把这份 APK 作为对外分发版本(官网、GitHub Release、其他渠道)
这样用户安装后,就能被 Play 商店正常检测并更新。
三、核心技术方案
1. 签名配置(Tauri 侧)
-
生成 Upload Keystore(
.jks) -
在
src-tauri/gen/android/keystore.properties和build.gradle.kts中配置 release 签名 -
构建命令:
bashtauri android build # 生成 AAB tauri android build --apk # 生成本地测试用 APK(Upload Key 签名)
2. 服务账号准备(一次性)
- Google Cloud Console 创建服务账号
- 启用 Google Play Android Developer API
- 下载 JSON 密钥文件
- 在 Play Console → 用户和权限 中邀请该服务账号,并授予「发布管理」或「测试轨道发布」权限
- 将 JSON 内容存入 GitHub Secrets(
PLAY_SERVICE_ACCOUNT_JSON)
3. GitHub Actions 自动化流程
推荐完整链路:
arduino
Tauri 构建 AAB
↓
上传 AAB 到 Play Console(draft 状态)
↓
等待 Google 生成已签名 APK
↓
调用 Generated APKs API 下载 Universal APK
↓
上传到 GitHub Release / 自有 CDN / 其他渠道
↓
(可选)将 draft 版本推进到正式发布
关键 API:
edits.bundles.upload:上传 AABgeneratedapks.list:获取可下载的 APK 列表generatedapks.download:下载已签名的 Universal APK
也可用现成工具:
r0adkll/upload-google-play(上传 AAB)- fastlane 的
download_universal_apk_from_google_play(下载已签名 APK)
四、关键注意事项
-
签名差异是正常的
本地 APK(Upload Key)与商店版(App Signing Key)永远不同,这是设计如此。
-
对外分发必须用 Google 签过名的 APK
只有从 Play Console / API 下载的「Signed Universal APK」才能与商店版互相覆盖。
-
Service Account 权限要足够
至少需要测试轨道发布权限,下载 Generated APK 建议给更高权限。
-
处理延迟
AAB 上传后,Google 生成最终 APK 通常需要几分钟,脚本中需适当等待或轮询。
-
安全
Service Account JSON 只能存在 GitHub Secrets 中,绝不能提交到仓库。
五、最终推荐实践
- 开发测试:继续用本地 Upload Key 签名的 APK,安装前先卸载商店版
- 对外分发 / 官网下载:始终使用从 Play 下载的已签名 Universal APK
- 自动化发版:GitHub Actions 完成「构建 → 上传 AAB → 下载已签名 APK → 发布」全流程
通过以上方案,既能享受 Play App Signing 的安全性与优化能力,又能实现完全自动化的多渠道发布,同时保证用户安装体验一致。
