Android APK 自托管发布清单:签名、升级与下载完整性
把 APK 放到网站并提供一个下载按钮,看起来已经完成发布。真正困难的部分会在下一次更新时出现:新包能否覆盖旧包、用户如何确认文件没有损坏、签名密钥是否还能找到,以及新版 Android 的开发者验证是否已经准备好。
Debug APK 不是长期发布包
assembleDebug 生成的 APK 会使用 Android SDK 自动创建的 debug 证书,并允许调试。它适合开发机、模拟器和临时测试,不适合作为长期公开下载。debug keystore 本来就是不安全的开发凭据,应用商店也不会把 debug 签名当作正式发布身份。
公开版本应使用 release variant,并由自己的长期密钥签名:
./gradlew clean assembleRelease
更新身份由三个值共同决定
一个已安装应用能否被新 APK 原地更新,至少取决于:
applicationId与已安装应用一致;- 新 APK 的签名证书与既有版本匹配,或符合已建立的密钥轮换关系;
versionCode高于设备上的版本。
versionName 是展示给用户看的字符串,versionCode 才是 Android 比较新旧的正整数。把两者都写进发布记录,但不要用文件名或 versionName 代替系统版本判断:
android {
defaultConfig {
applicationId = "com.example.puzzle"
versionCode = 12
versionName = "1.3.0"
}
}
更换签名证书而没有正确的轮换方案,通常会让系统把新包视为不能覆盖旧应用的另一个发布身份。用户只能卸载旧版再安装,现有本地数据也可能随之丢失。因此,签名密钥的备份策略与源代码备份同样重要。
密钥不能进入仓库
release keystore、别名和密码不应提交到 Git。可以让 CI 从受保护的 secret 注入临时文件和环境变量,构建结束后清理工作目录。密钥本体至少保留一份离线加密备份,并记录恢复步骤,而不是只依赖某台开发电脑。
发布前验证 APK,而不是相信文件名
Android SDK Build Tools 中的 apksigner 可以检查签名是否适用于 APK 支持的 Android 版本,并输出证书信息:
apksigner verify \
--verbose \
--print-certs \
app-release.apk
CI 应保存预期的 SHA-256 证书指纹,并在每次构建后比对。这样能及时发现构建机使用了错误 keystore。注意签名后再修改 APK 会破坏签名;如果流程单独运行 zipalign,必须先对齐再签名。
还应读取实际制品的包名、versionCode、versionName、最低 SDK 和是否可调试,而不是只检查 Gradle 文件。构建配置、flavor 或缓存都可能让最终 APK 与预期不同。
SHA-256 校验的是文件,不是开发者身份
为下载文件发布 SHA-256 很有价值:用户或自动化可以确认下载没有截断,也能判断服务器上的 APK 是否与本次发布制品完全相同。
shasum -a 256 app-release.apk
但如果攻击者能同时替换 APK 和网页上的哈希值,校验仍会“通过”。哈希解决完整性核对,APK 签名负责更新身份,HTTPS 保护传输;三者不能互相代替。更完整的发布记录应包含文件大小、SHA-256、签名证书 SHA-256 指纹、版本号和发布日期。
下载 URL 需要兼顾稳定与可追溯
直接覆盖 app.apk 方便,却让缓存、故障回滚和问题定位变得困难。更稳妥的方式是保存不可变的版本化文件,例如:
/downloads/puzzle-1.3.0-12.apk
页面上的“最新版本”按钮可以更新到这个文件,旧 URL 则保留一段时间。服务器应返回正确的内容长度和 APK MIME 类型 application/vnd.android.package-archive,避免 HTML 错误页以 200 OK 冒充 APK。部署后应从公网检查状态码、大小和 SHA-256。
发布页面也属于产品
用户从网站安装应用时,看不到商店自动提供的信息。下载页应该清楚显示应用名称、平台要求、版本、发布日期、更新说明、文件大小和校验值,并提供技术支持与隐私政策。安装未知来源应用所需的系统提示也应如实说明,不要诱导用户关闭设备安全功能。
同时测试全新安装和从当前公开版本升级。升级测试要使用真实旧版 APK 并保留数据,才能发现签名、版本号或数据库迁移问题。
2026 年还要准备开发者验证
截至 2026 年 9 月 18 日,Android 开发者验证已开放。9 月 30 日起,首阶段会在巴西、印度尼西亚、新加坡和泰国的认证设备上,针对参与的应用商店实施;官方计划从 2027 年开始扩展到全球认证设备。
官方 FAQ 说明,2026 年 9 月的首阶段尚不直接覆盖网站侧载,但建议在全球推广前完成验证。只在 Google Play 之外分发的开发者使用 Android Developer Console;同时使用 Play 的开发者可在 Play Console 管理相关包名。注册包名可能需要用既有私钥证明所有权,这再次说明签名密钥不能遗失。
把发布做成可重复流水线
一次可靠发布可以固定为以下顺序:
- 更新并检查
versionCode与versionName; - 从干净提交构建 release APK;
- 使用受保护的长期密钥签名;
- 用
apksigner verify --print-certs验证签名和证书; - 检查包名、版本、SDK、权限和 debuggable 标志;
- 运行自动测试,并在真实设备验证全新安装与升级;
- 生成 SHA-256、文件大小和发布记录;
- 上传版本化 APK,更新下载页面;
- 从公网重新下载并再次比对哈希;
- 保留上一个可用版本和明确的回滚步骤。
自托管 APK 的自由来自对整条交付链的控制,而不是少做几个步骤。只要签名身份、版本单调性、制品完整性和网页信息都进入自动检查,网站下载就能从一次性的文件分享,变成可以持续升级和审计的正式发布渠道。