HarmonyOS 7 ReleaseGuard 上架审核工程实录 04:module.json5 × DeviceTypes:支持设备、Profile 权限与包体有效性报告【鸿蒙心迹】
03 刚刚把图标、截图、应用描述和内容分级做成了 Listing Report。
第四篇我又回到底层包体。
原因很现实:AppGallery Connect 在真正解析 .app 时,会检查一批开发者本地完全可以提前确认的关系。当前 HarmonyOS 包解析错误文档里,和这一篇直接相关的典型场景包括:
998:
上传包不支持市场侧选择的设备类型
999:
使用了错误类型的 Profile
1000 / 1001 / 1002 / 1005:
Profile / Certificate 异常
1014:
HAP 未签名
7014:
包内权限与 Profile 请求权限不一致
这些错误没必要等上传以后才看见。
所以 04 新增一份 Package Report,专门回答:
这个
.app在“设备、Profile、权限、签名、包类型”几个基础层面,是否已经和本次发布计划一致。
本轮统一数据:
taskId:
release_20261002_04
bundleName:
com.example.releaseguard
versionName:
1.3.0
versionCode:
10300
targetApi:
26
compatibleApi:
20
artifact:
releaseguard_1.3.0.app
artifactSize:
18.4MB
packageType:
app
moduleCount:
1
hapCount:
1
entryModule:
entry
packageDeviceTypes:
phone / tablet
agcSupportedDevices:
phone / tablet
deviceTypeMismatch:
0
packagePermissions:
3
profilePermissions:
3
permissionSubset:
true
releaseProfile:
release_prod_202610
profileState:
VALID
certificateState:
RELEASE_VALID
signed:
true
parseChecks:
9 / 9
parseRisk:
0
status:
PACKAGE_REPORT_READY

一、04 不再读工程配置,而是读“构建后包体快照”
这一篇最重要的变化是输入。
01 还主要看:
app.json5
build-profile.json5
04 更接近真实上传阶段,所以检查器读取的是构建后生成的:
PackageReportSnapshot
模型:
export interface PackageReportSnapshot {
taskId: string
bundleName: string
versionName: string
versionCode: number
targetApi: number
compatibleApi: number
artifactName: string
artifactSizeMb: number
packageType: string
modules: {
name: string
type: string
deviceTypes: string[]
permissions: string[]
signed: boolean
}[]
releaseProfile: string
profilePermissions: string[]
profileState: string
certificateState: string
}
这份 Snapshot 可以由构建脚本或包解析工具生成。
ArkTS 页面只展示结果。
这样报告反映的是:
真正要上传的包
而不是工程源码“理论上应该长这样”。
二、deviceTypes 要比较“包支持范围”和“市场选择范围”
当前包:
phone
tablet
AppGallery Connect 发布计划:
phone
tablet
所以:
deviceTypeMismatch=0
官方当前包解析错误码 998 已经明确说明:上传包如果不支持 AppGallery Connect 里为应用选择的设备类型,包解析会失败。
本地完全可以提前比较集合:
export class DeviceSupportAudit {
check(
packageDeviceTypes:
string[],
agcSupportedDevices:
string[]
): {
missing: string[]
passed: boolean
} {
const missing =
agcSupportedDevices
.filter(
device =>
!packageDeviceTypes
.includes(device)
)
return {
missing,
passed:
missing.length === 0
}
}
}
注意关系是:
AGC 选择的设备
必须被包覆盖
不是要求两边字符串完全一模一样。
这和官方错误描述“package does not support selected devices”更一致。
三、为什么 deviceTypes 不能只看 AppScope
真正设备声明位于模块层。
所以 04 会把每个 HAP / module 的:
deviceTypes
展开。
当前只有:
entry
一个模块:
phone
tablet
因此汇总结果很简单。
如果以后有:
entry-phone
entry-tablet
feature-pc
报告必须按模块汇总,而不是只读一个全局字段。
这也是 moduleCount=1 / hapCount=1 进入诊断数据的原因。
四、Profile 权限必须覆盖包内声明权限
这是 04 最值得工程化的一条。
AppGallery Connect 当前 HarmonyOS 包解析错误 7014 明确说明:
包中配置的权限必须是 Profile 请求权限的子集。
当前:
packagePermissions=3
profilePermissions=3
permissionSubset=true
检查器:
export class ProfilePermissionAudit {
check(
packagePermissions:
string[],
profilePermissions:
string[]
): {
missing: string[]
subset: boolean
} {
const profileSet =
new Set(
profilePermissions
)
const missing =
packagePermissions
.filter(
permission =>
!profileSet
.has(permission)
)
return {
missing,
subset:
missing.length === 0
}
}
}
这和 02 的隐私检查不是同一件事。
02 问:
权限用得合不合理
有没有披露
04 问:
这个 release Profile
技术上有没有覆盖包里声明的权限
两个层面都必须通过。
五、Profile 状态与 Certificate 状态也要进报告
当前:
releaseProfile:
release_prod_202610
profileState:
VALID
certificateState:
RELEASE_VALID
官方包解析错误文档里已经列出多种 Profile / Certificate 问题:
Profile 无效
Profile 不属于该应用
Profile 过期
Profile 与证书不匹配
证书过期
证书未生效
证书无效
ReleaseGuard 不复制所有证书验证逻辑。
真正证书链校验可以由构建阶段工具完成。
04 只要求 Package Report 必须带一个清晰状态:
VALID
否则发布门禁直接 BLOCK。
六、HAP 签名必须在包体报告里明确可见
当前:
signed=true
因为官方错误 1014 就是:
HAP has not been signed
这种错误太基础,不应该等上传以后才发现。
报告里每个 HAP 都要有:
signed
signatureIdentity
当前单 HAP:
entry
signed=true
所以通过。
如果未来多模块:
只要有一个 HAP unsigned
→ PACKAGE_BLOCKED
七、packageType 也要和应用类型对得上
当前:
packageType=app
AppGallery Connect 包解析文档还存在:
1011:
包不是 HarmonyOS app
1026:
包类型和应用类型不匹配
ReleaseGuard 04 因此把 packageType 做成显式字段。
这看起来像“不会配错”,但 CI 里如果有人复用错误构建任务,完全可能产出另一个类型的包。
工具应该让这种错误在上传前直接可见。
八、目标 API 继续只做本次发布计划校验
本轮:
targetApi=26
compatibleApi=20
和 01 一样,ReleaseGuard 不宣称:
AppGallery 永远要求 API 26
它只检查:
targetApi
符合本次 release-policy.json
compatibleApi
不高于 targetApi
市场要求未来变化时,只更新发布策略,不改 ArkTS 业务代码。
九、9 个 parseChecks 怎么组成
当前 9 项:
1 bundleName 与发布上下文一致
2 packageType=app
3 module / HAP 数量可解析
4 package deviceTypes 覆盖 AGC 选择
5 package permissions 是 Profile permissions 子集
6 release Profile 状态 VALID
7 certificate 状态 RELEASE_VALID
8 所有 HAP signed=true
9 artifact / version / API 与 Release Context 一致
全部通过:
9 / 9
parseRisk=0
进入:
PACKAGE_REPORT_READY
这个状态比 01 的 PACKAGE_READY 更靠近真正上传阶段。
01 是工程配置预检。
04 是构建后包体报告。
十、DevEco 图里最值得看的是两条“子集 / 覆盖”关系
开发图:

红色标注的两条关系:
package permissions
⊆
release Profile permissions
以及:
AGC selected devices
⊆
package deviceTypes
HiLog:
taskId=
release_20261002_04
package devices=
phone,tablet
agc devices=
phone,tablet
mismatch=
0
package permissions=
3
profile permissions=
3
subset=
true
profile=
release_prod_202610
profileState=
VALID
certificate=
RELEASE_VALID
signed=
true
artifact=
releaseguard_1.3.0.app
size=
18.4MB
modules=
1
hapCount=
1
targetApi=
26
parseChecks=
9/9
parseRisk=
0
status=
PACKAGE_REPORT_READY
这两条集合关系是 04 最核心的工程判断。
十一、手机图把包体解析结果变成发布负责人能读懂的报告
最终运行图:

它不要求发布负责人去翻:
module.json5
profile
证书
包解析日志
页面直接告诉你:
设备支持是否覆盖
Profile 权限是否覆盖
签名是否有效
HAP 是否已签名
包类型是否正确
9 项解析是否通过
最终:
PACKAGE_REPORT_READY
十二、把官方错误码映射成内部 Risk,而不是冒充服务端错误
ReleaseGuard 会维护一份本地映射:
DEVICE_TYPE_MISMATCH
↔ AGC 998 场景
PROFILE_PERMISSION_MISMATCH
↔ AGC 7014 场景
WRONG_PROFILE_TYPE
↔ AGC 999 场景
UNSIGNED_HAP
↔ AGC 1014 场景
注意是:
“对应场景”
而不是:
“本地工具已经得到官方错误码”
只有 AppGallery Connect 服务端真正返回的,才叫官方解析结果。
这种措辞必须严谨。
十三、包体报告还应该保存原始证据
如果检查失败,只给:
permissionSubset=false
不够。
报告至少保存:
缺失权限列表
AGC 设备选择
package deviceTypes
Profile ID
certificate serial / validity
HAP names
artifact hash
这样真正上传失败时可以直接和服务端错误对照。
发布工具越接近门禁,证据链越重要。
十四、04 最后固定九组故障注入
正常 9/9 之外,固定制造:
1 AGC 勾 tablet,包只有 phone
2 package 多一个 Profile 未授权权限
3 Profile state=EXPIRED
4 Certificate=EXPIRED
5 HAP signed=false
6 packageType=atomicService
7 artifact version 与 Snapshot 不一致
8 targetApi 与 release policy 不一致
9 多 module 中一个模块 deviceTypes 配错
每一组都应该得到明确 Risk。
工具只有能抓住“故意错的包”,才有资格进入 CI。
十五、下一篇开始处理“版本升级”而不是“单个包是否合法”
04 到这里,单个 1.3.0 包已经完成:
基础身份
隐私
商店元数据
包体解析
05 会把它和 AppGallery Connect 的历史版本放在一起比较。
真正的问题会变成:
1.3.0 相比 1.2.9
版本号是不是递增
签名身份有没有连续
支持设备有没有被意外删减
权限有没有突然扩张
灰度发布计划是不是和风险等级匹配
这时 ReleaseGuard 才会从“单次上架预检”进入“版本演进预检”。
十六、Package Report 还要检查“模块声明内部是否自洽”
04 当前只有一个 entry 模块,所以很多问题看不出来。
多模块以后,至少还要确认:
每个 module name 唯一
entry module 数量符合应用结构
deviceTypes 不出现互相冲突组合
每个 HAP 都有可识别签名
模块 version / bundle 上下文一致
AppGallery 的包解析错误里已经存在多种模块结构相关错误。
ReleaseGuard 不需要预测所有服务端解析规则,但可以先做“工程内部自洽性”。
例如两个模块意外用了同名:
entry
entry
即使构建工具某一步还能产出文件,也不应该让这种包继续走到上传阶段。
十七、权限子集检查要输出 missing 列表,而不是只有 false
如果最终只有:
permissionSubset=false
发布负责人还是不知道该怎么办。
所以失败报告应该直接给:
missingInProfile:
ohos.permission.CAMERA
ohos.permission.READ_IMAGEVIDEO
然后给出处理建议:
重新申请 release Profile
确保 Profile 请求权限覆盖包内声明
重新签名并重新构建
这和官方 7014 的处理方向保持一致。
工具最有价值的地方不是告诉你“失败了”,而是把下一步定位成本压低。
十八、设备覆盖检查还要区分“缺失”和“额外”
当前:
package:
phone / tablet
AGC:
phone / tablet
完全一致。
未来可能出现:
package:
phone / tablet / pc
AGC:
phone / tablet
这时并不是 998 场景,因为 AGC 所选设备仍然被包覆盖。
所以报告需要同时输出:
missingFromPackage
extraInPackage
真正 Blocker 是:
missingFromPackage.length > 0
extraInPackage 更多是提醒发布负责人确认:
这个包支持了额外设备,但本次市场发布计划没有选择它。
这类差异不一定错误,却值得可见。
十九、Profile 与 Certificate 的有效期应该设置提前预警
如果证书今天还有效,但三天后过期,而版本计划明天提交,纯 boolean:
VALID
信息不够。
ReleaseGuard 最终还会保存:
profileExpireAt
certificateExpireAt
daysToExpire
团队门禁可以设置:
< 14 天
→ WARNING
已过期
→ BLOCKER
14 天只是团队策略,不是 HarmonyOS 系统规则。
这种提前预警能避免“今天本地通过、排到审核时凭据已经过期”的尴尬情况。
二十、包体大小应该作为趋势指标,而不是只看是否超上限
当前:
18.4MB
从市场规则角度远没有触发手机 / 平板 HAP 上限,但 ReleaseGuard 仍会和上一版比较。
例如:
1.2.9:
14.8MB
1.3.0:
18.4MB
增长超过 20%。
即使合法,也值得问一句:
增加的是资源
三方库
多语言文件
还是误打进去的测试数据
所以 Package Report 还会给:
artifactSizeDelta
moduleSizeBreakdown
这属于性能 / 发布质量预警,不是 AppGallery 硬规则。
二十一、签名连续性先在 04 记录身份,05 再做历史比较
04 当前只确认:
signed=true
certificate=RELEASE_VALID
但真正版本升级还关心:
1.2.9 和 1.3.0
是不是同一条发布签名身份
所以这一篇会把:
certificate fingerprint
profile identity
signingConfig
写进 Package Report。
先记录,不在 04 下结论。
05 再去 Version History 里和上一个正式版本比较。
这样同一个字段在连载里是持续演进的,不是第五篇突然重新造一个 Signing 模块。
二十二、解析报告必须绑定 artifact hash
和 01 一样,04 报告如果不绑定 hash,就有可能出现:
报告检查 A 包
上传步骤拿 B 包
所以最终 Package Report 至少包含:
artifactName
artifactSha256
artifactSize
versionCode
buildTaskId
上传步骤必须重新校验。
只要 hash 不一致:
PACKAGE_REPORT_STALE
重新生成报告。
这条规则会一直延续到 06 的 CI Release Gate。
二十三、包解析失败风险应该分“官方已知映射”和“项目自定义”
最终报告里会把风险分两组:
AGC_MAPPED_RISK
PROJECT_RISK
例如:
DEVICE_TYPE_MISMATCH
→ AGC_MAPPED_RISK
PROFILE_PERMISSION_MISMATCH
→ AGC_MAPPED_RISK
ARTIFACT_SIZE_GROWTH
→ PROJECT_RISK
CERTIFICATE_EXPIRY_WARNING
→ PROJECT_RISK
这样发布负责人不会把团队自己的质量规则误解成 AppGallery 官方硬限制。
技术文章里也应该保持这种边界。
二十四、04 的 Package Report 最终会成为 05 的对比基线
04 输出:
PackageReport_1.3.0.json
05 不会重新扫描所有数据再自行解释。
它直接读取:
上一正式版本 Package Report
当前候选版本 Package Report
比较:
versionCode
签名身份
deviceTypes
permissions
artifactSize
targetApi
这样 ReleaseGuard 从 04 开始已经不只是“当前包能不能发”,而是在为版本演进建立可比较历史。
二十五、PACKAGE_REPORT_READY 的最终含义
这个状态至少代表:
包类型正确
包身份正确
设备支持覆盖发布计划
Profile 权限覆盖包内权限
Profile / Certificate 有效
HAP 已签名
模块结构可解释
产物与报告绑定
没有当前已知 Blocker
它仍然不代表:
AppGallery 服务端解析一定 100% 通过
服务端可能还有本地无法复制的校验。
ReleaseGuard 的目标始终是:
把确定、重复、结构化、可提前发现的问题尽量消灭在上传之前。
这才是 04 这份 Package Report 的边界。
二十六、最终包体报告还要保留“人工可读摘要”
JSON 适合 CI,但发布负责人更需要一段几秒钟能读完的摘要。
所以 ReleaseGuard 会把报告压缩成:
设备:
phone / tablet,覆盖正常
权限:
3 / 3,Profile 子集正常
签名:
release_prod_202610,证书有效
包:
releaseguard_1.3.0.app,18.4MB
风险:
0
这种摘要不会替代详细证据,但很适合放到发布单、群通知或审批卡片里。
团队真正需要的是:
一眼知道能不能继续
需要时又能下钻到完整证据
而不是让所有人都打开几十行 JSON。
二十七、04 最后还会跑一次“上传前快照冻结”
和 01、03 一样,进入下一阶段前会生成新的:
packageReportContextId
它由:
artifact hash
deviceTypes
permission set
profile identity
certificate identity
version
共同计算。
后续任何一项变化:
contextId 改变
04 的报告立刻标记:
STALE
这样即使某个人在检查以后重新申请了 Profile、改了权限、重新构建了 .app,也不会继续拿旧的 9/9 报告去走上传。
这种“结果和输入绑定”的机制,才是发布门禁真正可靠的基础。
二十八、从 01 到 04,ReleaseGuard 已经形成一条连续证据链
目前四篇不是四张独立检查表,而是:
01
包名 / 版本 / 签名预检
02
权限 / 隐私 / SDK 映射
03
商店文案 / 素材 / 分级
04
构建后包体 / deviceTypes / Profile 权限
每一层都输出自己的 Snapshot,同时引用同一个发布上下文。
这样 05 比较历史版本时,不需要再从头问:
这个包是谁
有哪些权限
支持什么设备
用了什么签名
这些信息已经被前四篇稳定记录。
这也是整个连载坚持“同一个项目持续演进”的意义:后面的能力建立在前面的证据之上,而不是每一篇重新造一个上架 Demo。
参考资料
- AppGallery Connect:Package Parsing Error Codes (HarmonyOS)
https://developer.huawei.com/consumer/jp/doc/app/agc-help-harmonyoserror-0000001651912985 - AppGallery Connect:Configuring a Privacy Description
https://developer.huawei.com/consumer/es/doc/app/agc-help-release-app-privacy-desc-0000002313477969 - AppGallery Connect:Version History
https://developer.huawei.com/consumer/fr/doc/app/agc-help-maintain-version-history-0000002236334582
更多推荐

所有评论(0)