功能全部就绪之后,发布工程要回答的问题变得朴素:这个包,真的是我们以为的那个包吗?元数据对不对、签名是不是发布证书、内容干不干净、构建新不新鲜。这篇按我们 P7 阶段的真实门禁讲这四问。
1. 先搞清楚:鸿蒙工程里元数据住在哪
Android 开发者迁到鸿蒙,第一个容易找错的地方就是版本元数据的位置。鸿蒙 Stage 模型工程的配置是两层:
AppScope/app.json5 # 应用级:bundleName / vendor / versionCode / versionName entry/src/main/module.json5 # 模块级:abilities / requestPermissions / deviceTypes关键事实:versionCode / versionName / vendor 只在AppScope/app.json5,module.json5里没有。新人升版时去 module.json5 里翻 versionCode,找不到就自己加一个——编译不一定报错,但市场认的还是 AppScope 那份,于是"我明明升版了,后台说 versionCode 没递增"的事故就这么发生。另一个三元组也别漏:compileSdkVersion/targetSdkVersion/compatibleSdkVersion(本工程冻结为 24 / 24 / 23,见 ADR-001)——targetSdkVersion影响系统的兼容性行为和市场的分发范围,发布前要和基线一起核对。
发布元数据在 P7 第一天冻结成契约,注意是冻结成脚本里的常量,不是 Wiki 里的表格:
# Frozen packaging contract (P7-T01) EXPECTED_BUNDLE='com.xiangshikeji.speaklab' EXPECTED_VENDOR='xiangshikeji' EXPECTED_VERSION_NAME='1.0.0' MIN_VERSION_CODE=1门禁逐项 grepAppScope/app.json5核对:bundleName 是否漂移、vendor 是否还是example占位(单独一条显式检查——模板工程最常见的发布事故)、versionName 精确匹配、versionCode ≥ 基线。
几个字段的纪律(B01 提过,这里按发布视角重申):
bundleName:创建 AGC 应用时与之绑定,上架后不可改,核对它=核对"这个包会更新到正确的应用条目下";
versionCode:市场的单调轴,AGC 后台强制每次提交递增。门禁只查下界(≥1),递增靠发布流程纪律——内部用 RC 标签(
speaklab-1.0.0-rc.N)管理候选,正式递增发生在提交那一刻;vendor:审核可见的主体标识,
example占位会直接暴露"没认真准备"。
2. 签名:发布证书是上架与侧载的分水岭
鸿蒙的签名体系对新手是一套新概念,最小可用的心智模型是四样东西:
材料 | 来源 | 作用 |
|---|---|---|
私钥 | DevEco 本地生成 | 签名的"笔",丢了无法续签同一应用 |
发布证书 | 用 CSR 在 AppGallery Connect 申请 | 证明"笔"属于你 |
发布 Profile | AGC 按 bundleName + 证书签发 | 声明"这个应用允许被这把笔签" |
| 工程内配置 | 把上面三样接进构建 |
DevEco 默认帮你管一套调试签名(自动化申请、7 天有效期的调试 Profile 之类),跑真机调试很顺滑,但调试证书签的包不能上架。发布构建必须显式切到发布signingConfigs——所以门禁里有一条核对:Release 构建配置引用的是发布 profile 路径,而不是 DevEco 自动生成的调试材料。
纪律有三条:签名材料不进仓库(.p12/.cer/.p7b 全部 gitignore,靠团队密钥渠道分发);签名信息不进日志(构建脚本不打印 alias 密码等);上架前最后核对一遍证书有效期——证书过期导致的"更新包签名校验失败"是发行期最难看的事故。
3. 卫生检查的另一面:内容与产物一致性
元数据和签名之外,卫生门禁还核对一组"内容事实":Release/Debug/活动三个 composition seam 文件都在(B02 的机制赖以存在)、凭据控制器和 Preferences port 没有越界(B15/B09 的红线)、切换/构建/审计三个脚本在位。原则是:Release 的"干净"由一组可枚举的事实构成,每个事实都有静态证据。
产物层面还有一招值得单独说:解包审计。HAP 本质是 zip 结构的包,用 SDK 自带的解包工具(app_unpacking_tool.jar)或干脆 unzip 展开,就能核对resources/rawfile/里的词库与法律文本在不在、ets/目录里有没有不该出现的 Debug 夹具模块。我们的双 HAP 隔离审计(Debug 包与 Release 包互相核对)就是在产物层面证明:Fake 夹具物理存在于 Debug 包、物理不存在于 Release 包——不是"理论上不会编进去",是"解开看过了,确实没有"。
门禁文件头还有一句重要自我约束:
Proves static facts only — never substitutes for device RC matrix.
静态门禁证明"文件层面的事实",它不声称替代真机 RC 矩阵(那是 P7-T04 的活)。每种验证手段说清自己能证明什么、不能证明什么——这和 B16 的三层区分是同一纪律。
4. 干净重建:验收构建必须从零开始
团队被"旧产物冒充新构建"坑过之后,立了干净重建原则:独立验收的构建必须从 clean 开始——hvigorw clean清掉增量缓存,最好换临时目录重新检出。禁止拿entry/build/里躺着的旧 HAP 改个名就当验收包。
这条原则的深层原因:Hvigor 增量构建的缓存里可能留着"上一个实验"的产物,而源码时间戳看不出来(B18 讲的变异假存活,根因是同一个)。你验收的可能是一个从未存在过的源码状态的构建——它通过还是失败都没有意义。我们的构建脚本(B01)默认先 clean,验收场景再加"临时目录干净检出",并且明确不强制git worktree——手段可以灵活(临时目录/清缓存检出均可),原则只有一条:产物必须能从当前源码完整复现。
5. SHA-256 取证:让"同一个包"可引用,并分清 HAP 与 App Pack
每次验收构建打印 SHA-256(B01 的脚本习惯),在发布流程里它升级为取证语言:任务单里写accept HAP Release=f09f7a65…,真机hdc install后核对的也是它。"你测的是哪个包?"这个问题从此一个字的歧义空间都没有。
但鸿蒙发布有一个容易混淆的产物差异要说清:真机侧载安装的是 HAP,上架 AppGallery 提交的是 App Pack(.app)——后者是assembleApp的产物,把各模块 HAP 打包成市场分发格式。两个文件、两个 hash,引用时写明是哪个。我们的口径:真机 RC 矩阵验收用 HAP 的 hash,上架提交记录 App Pack 的 hash,任务单里两者并存,谁也不冒充谁。双 HAP(Debug+Release)一起给 hash,配合 B02 的隔离审计,构成完整的"这个包干净且新鲜"的证据链。
6. 发布前清单
AppScope/app.json5:bundleName / vendor / versionName / versionCode 门禁全绿;SDK 三元组与基线一致签名:Release 构建引用发布证书 + 发布 Profile,非调试材料;材料不进仓库不进日志
三个 seam 文件在位;双 HAP 解包审计通过(Debug 夹具不进 Release)
干净重建:clean + 新鲜源码,非旧产物
HAP 与 App Pack 的 SHA-256 分别记录进验收文档
静态门禁 ≠ 真机验证:
hdc install真机 RC 矩阵另行执行
7. 小结
元数据只住
AppScope/app.json5;module.json5 里没有版本字段,别找错地方。发布签名四件套:.p12 / .cer / .p7b / signingConfigs;调试证书签的包上不了架。
卫生=可枚举事实的静态证据;解包审计把"干净"从推断变成目击。
验收构建必须干净重建;SHA-256 是引用构建产物的唯一语言,HAP 与 App Pack 分开记。