## 起因 用户 2026-11-01:「家书已经有人做了,八月份刚上线的」。 核实:「家书 HomeBook」(广州家书科技有限责任公司,粤ICP备2026096420号, 2026-06 成立、08 上线)。功能**部分重合**(家庭记录 + 相册 + 家谱)。 华为审核指南 1.3「应用名称不得和其他应用名称相同,避免混淆」, 虽然个人与企业主体查重不互通、技术上能过,但被人工驳回概率高。 ## 定名过程(用户逐个否掉) | 候选 | 否决原因 | |---|---| | 寸草 | — | | 家卷 | ❌ 与「家眷」同音,口头传播会打错字 | | 家时光 | ❌ App Store 已有「家·时光」定位几乎一致;且「家+时光」是常见组合,辨识度低 | | 家纪 | ❌ 已有重名 | | **岁月家** | ✅ 搜不到同名应用;是口号的直接展开(岁月 + 家) | ## 最终定稿(用户明确指定) ``` 应用名 岁月家 主标语 一家人用岁月写成的一本书 ← 不变 一句话简介 一家人用岁月写成的一本书 ← 改为与标语相同 官网标题 岁月家 · 一家人用岁月写成的一本书 英文名 FamilyBook ← 不变 包名 familybook.yangyq.net ← 不变 ``` ## 改动范围(17 + 18 处,12 个文件) ### 应用名(17 处) `AppScope/resources/base/element/string.json` 的 app_name, `entry/.../string.json` 的 16 条(应用名、卡片名、无障碍描述)。 ### 用户可见文案(18 处) `FbBackgroundSync` / `EntryAbility`「正在同步家书数据」、 `FbAttachOpen`「家书附件」相册名、`FbHttp` 地址校验失败提示、 `FbCardData` / `FbCardMediaData` 卡片空态「先在「家书」里填写服务器地址」、 `TopBar` / `Drawer` / `FbLoginPage` 的应用名文本、`FbSettingsPage` 的说明。 ## 刻意不改 - **包名 / bundleName**(用户明确要求不变,且改了等于换一个应用) - **英文名 FamilyBook**、目录名、仓库名(改了会让 git 历史、部署脚本、证书路径全跟改) - **代码注释**里 200+ 处「家书 FamilyBook · 某模块」—— 不影响运行时, 改了只会制造噪音 diff,让将来 blame 变难 - **主标语**里一个字都没动 ## 验证 ### 编译 `BUILD SUCCESSFUL`,33 tasks。 ### 产物实测 解包 `.hap` 的 `resources.index`: - 「岁月家」出现 **17** 次 - 「家书」出现 **0** 次 ### 全局一致性校验(31 项全过) `_tooling/check_rename.js`: - 客户端 app_name / EntryAbility_label / 产物内容 - .ets 用户可见文案无残留(排除注释) - 服务端非注释代码无残留 - `Auth::homeTitle()` 用「某某某的家庭岁月」 - `DEFAULT_SLOGAN` 未被改动 - 官网线上 5 个页面无「家书」、标题含岁月家、渲染后 h1 是品牌名 - 材料 app_name / 一句话简介 / 包名 / versionCode / 域名 ⚠️ 校验过程中我自己的判据出了 2 次假红: ① 注释识别不全(漏了 `/**` 单行块注释和 `<!--` HTML 注释)→ 补齐 isCommentLine ② 「为什么叫岁月家」整节重写后,旧断言还在查「书信」「家与书」 (那是**旧名字**的逻辑)→ 改成查「岁月」+「家」的拆解 ## 一处语义决策(问过用户) 网页端 `Auth::homeTitle()` 生成「某某某的家书」—— 这是**产品核心语义** (每个家有自己的那一本),直接换成品牌名会读成「某某某的岁月家」,不通。 用户定:改成 **「某某某的家庭岁月」**。 兜底(无姓名时)仍用品牌名「岁月家」。 ## 连带影响(不阻塞) - 上架材料 7 个文件已同步(含软著全称改为「岁月家家庭生活档案管理软件」) - 官网已部署,线上标题已是新名字 - 软著申请尚未提交 —— 正好一次写对新名字,不需要变更
11 KiB
华为正式发布证书申请 + 岁月家切 release 签名
一句话结论:现在用的是调试证书,它能装到自己手机,但不能上架、不能用于 APP 备案。 必须先生成正式发布证书(.cer)+ 发布 Profile(.p7b),再改
build-profile.json5切到 release。
一、先确认现状(已核实)
build-profile.json5 当前签名配置:
{
"name": "default",
"type": "HarmonyOS",
"material": {
"certpath": "/home/yongquan/code/cert/familybook/familybook.yangyq.net.debug.cer",
"keyAlias": "debugKey",
"profile": ".../familybook.yangyq.net.debug.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": ".../familybook.yangyq.net.debug.p12"
}
}
文件名里带 .debug. —— 这是调试证书。它的特征:
| 项目 | 调试证书 | 发布证书 |
|---|---|---|
| 有效期 | 约 90 天(会过期) | 1 年(可续) |
| 可装机范围 | 仅登记过的调试设备(UDID 白名单) | 任意设备 |
| 能否上架 AppGallery | ❌ 不能(审核报 991 / 1014) | ✅ 必须 |
| 能否用于 APP 备案 | ❌ 不能(备案要正式证书的公钥/MD5) | ✅ 必须 |
| 能否用于 Map Kit | ✅ 可以(这也是之前 #33 的前提之一) | ✅ 可以 |
实测当前调试证书的指纹
MD5 : 7D:0C:4B:46:B7:C1:C0:D2:3C:6E:43:16:E5:C9:96:A3
SHA256 : DF:21:A3:C0:9F:79:54:57:93:05:F8:5C:64:F8:0C:AD:86:F7:98:53:EE:3A:88:7C:1D:EC:95:D2:18:DF:3A:37
公钥 : MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEWidkGnDSOw3/HE2y2GHl+fpWBIa5S+IlnNrsGUvwC1I2QWvtqCHWmwFlFK95zKXiM8s9yV3VVXh7ivN8ZJO3SC5N1TCrvB2lpLMBwcz4DA0kgHCMm/wDec6kOHx1xvCR
⚠️ 这三项是调试证书的,不能拿去备案。备案必须是正式证书的。
二、申请正式发布证书(AGC 网页操作,约 10 分钟)
前置:确认开发者账号已实名
AGC → 右上角头像 → 「实名认证」。个人开发者需身份证 + 人脸/银行卡验证,通常 1–3 个工作日。 你之前上架过 SyncCalendar,说明已实名,可跳过。
步骤 1:生成 CSR + 密钥库(在 WSL 里做)
华为的 .cer 是用你本地生成的 CSR 去换的,私钥始终在你手里,不上传。
cd ~/code/cert/familybook
# 生成密钥库(PKCS#12)与 CSR
# ⚠️ 口令自己定,记牢 —— 每次打包都要输,丢了只能重新申请证书
keytool -genkeypair \
-alias familybook_release \
-keyalg EC -groupname secp384r1 -sigalg SHA384withECDSA \
-validity 3650 \
-keystore familybook.yangyq.net.release.p12 \
-storetype PKCS12 \
-dname "C=CN, O=yangyq, OU=personal, CN=familybook.yangyq.net" \
-storepass '<你的口令>' -keypass '<同一个口令>'
# 导出 CSR
keytool -certreq \
-alias familybook_release \
-keystore familybook.yangyq.net.release.p12 \
-storepass '<你的口令>' \
-file familybook.yangyq.net.release.csr
产出:
familybook.yangyq.net.release.p12(私钥,绝不上传、务必备份)familybook.yangyq.net.release.csr(这个拿去换证书)
💡 也可以直接在 DevEco Studio 里做:
Build → Generate Key and CSR,效果一样。 但你在 WSL 命令行做更可控,且方便脚本化。
步骤 2:在 AGC 上传 CSR,换回 .cer
- 登录 https://developer.huawei.com/consumer/cn/service/josp/agc/index.html
- 右上角「我的」→ 「用户与访问」 → 左侧 「证书管理」
- 点 「新增证书」
- 证书类型选 「发布证书」(Release,不是 Debug)
- 上传刚生成的
familybook.yangyq.net.release.csr - 提交 → 下载得到
familybook.yangyq.net.release.cer - 把这个
.cer放到~/code/cert/familybook/
⚠️ 一个账号最多 1 个发布证书(调试证书可多个)。若已有(SyncCalendar 用的那个), 需要先吊销旧的才能新建 —— 但吊销会让 SyncCalendar 的更新包签不了名, 所以建议:给岁月家单独申请前,先确认是不是共用同一个。
更稳妥的做法:同一个发布证书可以签多个应用(Profile 才是按应用绑定的), 所以直接用 SyncCalendar 那个发布证书也行,只需为岁月家新建一个 Profile。
步骤 3:创建发布 Profile(按应用绑定)
- 还在「用户与访问」→ 左侧 「Profile」
- 点 「新增 Profile」
- Profile 类型选 「发布」
- 绑定:
- 应用:选「岁月家」(若 AGC 里还没建这个应用,先去「我的应用 → 新建」建一个)
- 证书:选上一步那个发布证书
- 提交 → 下载得到
familybook.yangyq.net.release.p7b
⚠️ Profile 与包名绑定。岁月家包名
familybook.yangyq.net, 必须与 AGC 里创建应用时填的包名完全一致。
步骤 4:配置应用包名与指纹(备案也要用)
- AGC →「我的应用」→ 新建(如果还没建)
- 平台:HarmonyOS
- 应用名称:岁月家
- 包名:familybook.yangyq.net(一字不差,创建后不可改)
- 分类:实用工具
- 默认语言:简体中文
- 「项目设置 → 常规 → 应用」→ 添加公钥指纹
- 上传步骤 2 下载的
.cer,或直接填 SHA256 指纹
- 上传步骤 2 下载的
- 顺手把 「应用」的 Client ID 记下来(工单 #33 的 Map Kit 要用它)
三、切换到 release 签名(改代码)
build-profile.json5 目前只有 default 一个 signingConfig。不要直接改掉它
(否则日常调试也得用发布证书,很麻烦),而是新增一个 release 配置:
{
"app": {
"signingConfigs": [
{
// 保留原调试配置,日常装机继续用它
"name": "default",
"type": "HarmonyOS",
"material": {
"certpath": ".../familybook.yangyq.net.debug.cer",
"keyAlias": "debugKey",
"profile": ".../familybook.yangyq.net.debug.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": ".../familybook.yangyq.net.debug.p12",
"storePassword": "...",
"keyPassword": "..."
}
},
{
// 🆕 发布用(上架 / 对外分发)
"name": "release",
"type": "HarmonyOS",
"material": {
"certpath": "/home/yongquan/code/cert/familybook/familybook.yangyq.net.release.cer",
"keyAlias": "familybook_release",
"profile": "/home/yongquan/code/cert/familybook/familybook.yangyq.net.release.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "/home/yongquan/code/cert/familybook/familybook.yangyq.net.release.p12",
"storePassword": "<你的口令>",
"keyPassword": "<同一个口令>"
}
}
],
"products": [
{
"name": "default",
"signingConfig": "release", // ← 只改这一处
"targetSdkVersion": "26.0.0",
"compatibleSdkVersion": "6.1.1(24)",
"runtimeOS": "HarmonyOS"
}
]
}
}
打包:
source ~/.workbuddy/env/harmonyos.sh
cd ~/code/FamilyBook_harmonyos
# AppGallery 只收 .app(App Pack),不是 .hap
hvigorw --mode module -p product=default -p buildMode=release assembleApp --no-daemon
产出在 build/default/outputs/default/ 下的 .app 文件。
打完后务必自检这三条
# ① 确认是 .app 不是 .hap
ls -la build/default/outputs/default/*.app
# ② 确认签名用的是发布证书(不是 debug)
# 解包看签名信息,证书 CN 里不应出现 "debug"
unzip -l xxx.app | head
# ③ 确认版本号
unzip -p xxx.app/entry/... module.json | grep -E 'versionName|versionCode'
四、拿到正式证书后,顺手做 APP 备案
备案需要的三项,只有正式证书才能提供:
cd ~/code/cert/familybook
# ① 公钥
openssl x509 -in familybook.yangyq.net.release.cer -pubkey -noout
# ② 签名 MD5(备案用,**去掉冒号**!)
openssl x509 -in familybook.yangyq.net.release.cer -fingerprint -MD5 -noout
# ③ 包名(在 app.json5 里,已知)
grep bundleName ~/code/FamilyBook_harmonyos/AppScope/app.json5
⚠️ 备案系统的 MD5 字段要求去掉冒号,小写或大写都行但要去掉分隔符。 例如
7D:0C:4B:...→7d0c4b46b7c1c0d2...
五、证书有效期与续期
| 项 | 有效期 | 到期后果 |
|---|---|---|
发布证书 .cer |
1 年(自签发日) | 到期后无法用该证书签新包;已上架的应用仍可运行,但无法发布更新 |
发布 Profile .p7b |
跟随证书 | 同上 |
密钥库 .p12 |
你设的 validity(建议 10 年以上) | 丢了就永远无法再签同名应用 |
🔴 必须做的事
.p12私钥文件务必备份(至少两地)。它丢了 = 这个包名以后再也发不了更新, 只能换包名重新上架,等于从零开始积累下载量。- 在日历里设一个证书到期前 60 天的提醒。
- 续期方式:AGC 重新走一遍「新增证书 → 上传 CSR → 下载 .cer」,并重建 Profile。
用同一个密钥库重新生成 CSR 时,公钥不变,指纹也不变 —— 这样对已上架应用最省事。
六、常见坑(提前避开)
| 坑 | 现象 | 原因与解法 |
|---|---|---|
| 拿调试证书打包上架 | 上传成功,进审核后报 991 / 1014 包无效 | 必须用发布证书 + 发布 Profile |
| Profile 包名对不上 | 上传时报"包名与 Profile 不匹配" | Profile 绑包名,AGC 建应用时包名必须一字不差 |
| 忘了加公钥指纹 | Map Kit 报 1002600004 / 地图不显示 |
AGC「项目设置 → 常规 → 应用」添加 SHA256 指纹 |
| 私钥口令忘记 | 无法打包 | 只能重新申请证书(可用同一 CSR 会得到同公钥) |
传了 .hap |
AGC 不认 | 必须是 .app(assembleApp,不是 assembleHap) |
| versionCode 没递增 | 上传被拒 | 每次上传都要比上次大 |
七、时间预期
| 环节 | 耗时 |
|---|---|
| 本地生成 CSR | 2 分钟 |
| AGC 签发证书 | 即时(网页直接下载) |
| AGC 创建 Profile | 即时 |
| 本地切签名 + 打 release 包 | 5 分钟 |
| AppGallery 审核 | 1–7 个工作日(首次通常更久) |
| APP 备案(阿里云初审) | 1–2 个工作日 |
| APP 备案(管局审核) | 1–20 个工作日(多数省份约 7 天) |
备案是最慢的一环。建议顺序:先申请正式证书 → 同时提交 APP 备案 → 备案通过后再提审应用。 因为华为要求上架时填写 APP 备案号,没有备案号会被拒。