HarmonyOS 7 ReleaseGuard 上架审核工程实录 02:module.json5 × Privacy:权限声明、隐私标签与三方 SDK 合规映射【鸿蒙心迹】
01 解决的是“这个 .app 包是不是我要发布的那个包”。
包名、版本、release 签名、证书状态、设备类型和产物都已经通过,最终状态:
PACKAGE_READY
真正继续走到 AppGallery Connect 版本信息页以后,新的问题就不再是编译错误,而是权限、隐私政策、三方 SDK 和市场侧披露能不能互相对得上。
这类问题很适合做成工程预检,因为它们天然分散在不同地方:
module.json5
应用真实功能
隐私政策
三方 SDK 文档
AppGallery Connect 隐私标签
隐私描述
任何一处漏掉,最后看到的都是“审核不通过”,但开发阶段很难知道到底是哪一层没对齐。
AppGallery 当前隐私审核规则要求应用提供易于访问的隐私政策,应用内与 AppGallery Connect 提交的隐私政策内容应保持一致;如果应用及其第三方 SDK 处理个人信息,需要在隐私政策中说明收集使用的目的、方式、范围等。当前隐私描述文档还明确说明:如果包涉及敏感隐私权限或受限权限,要按要求填写权限用途说明;受限权限还涉及使用场景证明,并要求 release Profile 的权限和包内声明保持一致。
所以 02 的目标不是教“怎么写一份法律隐私政策”,而是建立一张工程侧合规映射表。
本轮统一数据:
taskId:
release_20261002_02
bundleName:
com.example.releaseguard
permissionCount:
3
sensitivePermissionCount:
2
permissions:
ohos.permission.CAMERA
ohos.permission.READ_IMAGEVIDEO
ohos.permission.INTERNET
thirdPartySdkCount:
2
SDK:
Remote Configuration SDK
Drive Kit
privacyDataItems:
7
agcPrivacyTagCount:
7
reasonMismatch:
0
sdkDisclosureMissing:
0
agcTagMismatch:
0
privacyPolicyUrlMatch:
true
inAppPolicyMatch:
true
checks:
10 / 10
status:
PRIVACY_READY

一、权限声明不能只看“module.json5 里写了没有”
第一层当然是工程权限。
当前示例的 module.json5 概念上包含:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.READ_IMAGEVIDEO",
"reason": "$string:media_reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.INTERNET"
}
]
}
}
具体某个权限是否必须填写 reason / usedScene、属于 system_grant 还是 user_grant、是否受限开放,都必须以当前 HarmonyOS 权限文档为准。
ReleaseGuard 不把所有权限当成同一种类型。
它会给每条权限补一份业务解释:
export interface PermissionUseCase {
name: string
feature: string
purpose: string
requestTiming:
'inuse' |
'startup' |
'system'
privacyDataKeys: string[]
}
例如:
CAMERA
→ 拍摄资料凭证
READ_IMAGEVIDEO
→ 用户主动选择待发布素材
INTERNET
→ 访问 AGC / 网络服务
检查的不只是“配置里有”,还要看:
配置 reason
业务 feature
隐私政策描述
能不能互相解释。
二、权限 reason 必须能对应真实功能
AppGallery 当前隐私审核规则要求,权限申请和使用遵循最小化原则,并清楚说明使用功能和场景,不能诱导授权。
所以 ReleaseGuard 把权限 reason 做成一条静态检查:
export class PermissionAuditRunner {
checkReason(
permission:
PermissionUseCase,
manifestReason:
string,
expectedKeywords:
string[]
): boolean {
if (
manifestReason
.trim()
.length === 0
) {
return false
}
return expectedKeywords
.some(
(
word:
string
) =>
manifestReason
.includes(word)
)
}
}
这不是 NLP 审核器。
它只是团队自己的“低成本错误拦截”。
例如 Camera 的业务是:
拍摄资料凭证
reason 却写:
优化用户体验
即使技术上能申请权限,这种描述也应该在提交审核前被标成:
reasonMismatch
本轮:
reasonMismatch=0
三、敏感权限和受限权限要单独建清单
当前 AppGallery Connect 的隐私描述文档已经明确:如果包涉及敏感隐私权限,需要说明每项权限的使用原因;如果涉及受限权限,还要按要求提供额外说明和使用场景材料,并确保 release Profile 请求的权限与包内声明一致。
所以 ReleaseGuard 不只统计:
permissionCount=3
还统计:
sensitivePermissionCount=2
restrictedPermissionCount
本轮把:
CAMERA
READ_IMAGEVIDEO
放入需要重点人工核对的权限清单。
真正是否属于当前版本审核页面里的“敏感 / 受限”分类,要以 AppGallery Connect 本次包解析结果为准。
工具的作用是提醒:
这些权限不能只看代码能不能跑,还要看发布资料有没有补齐。
四、三方 SDK 不能只在 oh-package.json5 里出现一次
真正容易漏的是三方 SDK。
当前 Demo 假设集成:
Remote Configuration SDK
Drive Kit
如果工程里只有依赖声明,没有一份“SDK 数据披露表”,隐私政策很容易忘记同步。
所以我新增:
export interface SdkDisclosureItem {
sdkName: string
purpose: string
permissions: string[]
dataTypes: string[]
transferMethod:
'NETWORK' |
'LOCAL_ONLY'
policyDisclosed:
boolean
agcTagMapped:
boolean
}
例如 Remote Configuration 当前官方 SDK 数据安全说明会列出它需要的网络权限和处理的数据类型;Drive Kit 的 SDK Privacy Statement 也会列出其处理的账号、设备、应用、API / 文件和网络等信息。
ReleaseGuard 不替 SDK 文档下结论。
它只要求:
每一个真实集成 SDK
必须有一条 Disclosure
如果依赖列表里有 SDK,而披露表没有:
sdkDisclosureMissing + 1
本轮:
sdkDisclosureMissing=0
五、隐私政策不是“有链接就通过”
AppGallery 当前审核规则要求:
应用内能访问隐私政策
AppGallery Connect 提交隐私政策链接
两边内容一致
而且政策要说明:
收集什么
为什么收集
如何处理
第三方是谁
用户如何行使权利
ReleaseGuard 当前把政策版本做成统一 ID:
privacyPolicyId:
privacy_1.3.0
应用内和发布配置都引用同一个版本。
检查器:
export interface PrivacyPolicySnapshot {
inAppPolicyId: string
agcPolicyId: string
developerName: string
appName: string
dataItems:
string[]
thirdPartySdks:
string[]
}
export function verifyPolicy(
snapshot:
PrivacyPolicySnapshot
): boolean {
return (
snapshot.inAppPolicyId ===
snapshot.agcPolicyId &&
snapshot.developerName
.trim()
.length > 0 &&
snapshot.appName
.trim()
.length > 0
)
}
本轮:
privacyPolicyUrlMatch=true
inAppPolicyMatch=true
这里的“match”是 ReleaseGuard 的版本一致性检查,不代表机器已经替法律合规做完最终判断。
六、隐私标签必须能反查到业务数据项
当前工程一共整理:
privacyDataItems=7
AppGallery Connect 隐私标签:
7
单纯数量相同还不够。
真正要比较集合:
业务数据项
↔
AGC 标签
例如:
设备信息
应用版本
网络信息
账号信息
文件元数据
相机内容
媒体文件
如果业务清单里有:
文件元数据
AGC 侧没映射:
agcTagMismatch
就应该在本地先出现风险。
本轮:
agcTagMismatch=0
七、权限、SDK、隐私政策、AGC 标签要形成四向矩阵
做到这里,我不再把这些东西当成四份文档。
ReleaseGuard 最终构造一个 Matrix:
export interface PrivacyMatrixRow {
dataKey: string
source:
'APP' |
'SDK'
feature: string
permission:
string | null
privacyPolicyMapped:
boolean
agcTagMapped:
boolean
}
export class PrivacyMatrixAudit {
audit(
rows:
PrivacyMatrixRow[]
): number {
return rows
.filter(
(
row:
PrivacyMatrixRow
) =>
!row.privacyPolicyMapped ||
!row.agcTagMapped
)
.length
}
}
每一条业务数据最终都能回答:
谁采集
为了什么
需要什么权限
隐私政策有没有写
AGC 标签有没有填
这比“我记得都配了”可靠得多。
八、为什么三方 SDK 披露必须单独做
AppGallery 当前多份 SDK 发布文档都会强调:如果应用集成第三方 SDK,需要在隐私政策中明确说明这些 SDK 收集个人信息的目的、方式和范围,否则发布可能被拒。
这类问题的难点是:
SDK 升级以后
数据项可能变
业务代码没改
隐私政策却应该改
所以 ReleaseGuard 会把:
sdk version
sdk privacy statement revision
也进入团队清单。
本轮图里为了简洁只显示两个 SDK 名称。
正式发布报告会保留对应版本。
九、10 个检查项怎么组成
当前 10 项:
1 requestPermissions 可解析
2 permission reason 对应业务
3 usedScene / 申请时机合理
4 敏感权限清单已人工确认
5 SDK 依赖都有 Disclosure
6 SDK 数据项进入隐私政策
7 业务数据项进入隐私政策
8 AGC Privacy Tags 完整映射
9 应用内隐私政策与 AGC 一致
10 权限 / Profile / 发布描述无已知缺口
结果:
10 / 10
才进入:
PRIVACY_READY
十、DevEco 图重点看三处“对齐”
开发图:

红色标注的不是 API 调用,而是三条关系:
module.json5 permission reason
↔
真实使用场景
三方 SDK 数据
↔
隐私政策
隐私政策
↔
AGC 隐私标签
HiLog:
taskId=
release_20261002_02
permissions=3
sensitive=2
sdk=2
privacyDataItems=7
agcPrivacyTags=7
reasonMismatch=0
sdkDisclosureMissing=0
agcTagMismatch=0
privacyPolicyUrlMatch=true
inAppPolicyMatch=true
checks=10/10
status=PRIVACY_READY
这些数字统一以后,提交版本信息页时心里会踏实很多。
十一、运行图是给发布负责人看的,不是给用户看的
最终运行图:

页面集中展示:
3 个权限
2 个 SDK
7 个隐私数据项
7 个 AGC 标签
0 个 reason 不匹配
0 个 SDK 披露缺失
0 个标签不一致
10 / 10
最终:
PRIVACY_READY
这个 internal 页面仍然不会出现在正式用户入口里。
它更像一张发布前“工程合规体检单”。
十二、隐私预检不能替代真实审核
这一点必须说清楚。
ReleaseGuard 可以检查:
配置是否齐
文档版本是否一致
权限与业务是否有明显错位
三方 SDK 是否漏登记
AGC 标签是否漏映射
但它不能自动证明:
所有法律义务都满足
隐私政策文字完全合规
审核一定通过
真正提交仍然要按 AppGallery 当前版本信息页、隐私描述、隐私声明和审核规则逐项确认。
工具的价值是把低级、重复、可结构化的问题尽量提前消掉。
十三、下一篇会从“合规文本”进入“商店素材”
包体和隐私都收稳以后,下一个经常被忽视的问题是:
应用名称
图标
截图
应用介绍
更新说明
内容分级
这些东西看起来属于运营,实际同样会影响审核和用户看到的市场页面。
03 会继续 ReleaseGuard,把:
工程里真正运行的版本
和:
AppGallery Connect 上提交的展示素材
做一致性检查。
十四、运行时申请权限的时机,也应该纳入发布检查
module.json5 只是声明层。
真实审核还会看:
什么时候弹权限
用户是否能理解
拒绝以后是否还能使用不相关功能
AppGallery 当前隐私规则也强调权限最小化、清晰说明使用场景,并避免首次启动频繁弹出敏感权限请求。
所以 ReleaseGuard 还维护:
export interface RuntimePermissionScenario {
permission: string
featureEntry: string
requestMoment:
'FIRST_LAUNCH' |
'ON_FEATURE_ACTION'
deniedFallback: string
}
当前团队规则:
CAMERA
→ 用户点击“拍摄凭证”时再申请
READ_IMAGEVIDEO
→ 用户点击“选择素材”时再进入选择链
INTERNET
→ 系统级网络能力按实际功能使用
如果 Camera 配置成:
FIRST_LAUNCH
而首页根本不需要拍摄,就会被 ReleaseGuard 标成:
EARLY_PERMISSION_REQUEST
它不是系统编译错误,却是非常值得发布前处理的体验和合规风险。
十五、拒绝权限后的降级路径也要有测试记录
权限审核不能只记录:
用户同意
还要验证拒绝。
例如 Camera 被拒绝以后:
手动上传已有图片
仍然应该可用。
如果用户拒绝一个非核心权限,应用就直接白屏或者退出,这和“最小必要”原则的产品目标明显冲突。
所以 Permission Matrix 继续增加:
deniedFallbackTested=true
发布负责人可以看到:
CAMERA
拒绝后仍可选择图库素材
READ_IMAGEVIDEO
拒绝后仍可保留手动文本发布
这种记录会比一条“权限已声明”更有价值。
十六、三方 SDK 版本变化要触发隐私清单重新确认
真正容易漏的不是首次接入,而是升级版本。
比如:
Remote Configuration SDK
1.2.0 → 1.3.0
即使业务调用没有变化,新版本的数据安全说明也可能更新。
所以 SdkDisclosureItem 再增加:
sdkVersion
privacyStatementVersion
reviewedAt
只要依赖版本变化:
Disclosure status
→ NEED_REVIEW
不能沿用上一版本自动绿灯。
这条规则会让发布流程稍微麻烦一点,却能避免“SDK 已经升级,隐私政策仍然写着旧数据范围”的典型问题。
十七、Privacy Tags 数量一致,不代表语义一致
本轮:
privacyDataItems=7
agcPrivacyTagCount=7
只是摘要。
实际审计不能写成:
return localCount === agcCount
正确做法是集合级比较:
export function diffTags(
local:
string[],
agc:
string[]
): {
missing: string[]
extra: string[]
} {
const localSet =
new Set(local)
const agcSet =
new Set(agc)
return {
missing:
local.filter(
item =>
!agcSet.has(item)
),
extra:
agc.filter(
item =>
!localSet.has(item)
)
}
}
可能出现:
本地有“文件元数据”
AGC 少了它
AGC 多填了“精确位置”
本地又根本不收集
总数仍然是 7,但语义已经错了。
所以最终 agcTagMismatch=0 来自集合比较,而不是数量比较。
十八、隐私政策也应该像代码一样有版本
很多项目把隐私政策当成一个永远不变的 URL。
ReleaseGuard 更倾向于记录:
policyId
policyRevision
publishedAt
checksum
本轮:
privacy_1.3.0
和应用版本一起发布。
当权限、SDK 或数据用途变化时:
Privacy Matrix changed
→ policy revision must change
如果 Matrix 变了,政策 revision 还没变:
POLICY_STALE
直接提醒发布负责人人工确认。
这不是强制要求“每个 App 版本一定改隐私政策”,而是让变化真正可追踪。
十九、第三方信息不能只写 SDK 名称
AppGallery 隐私审核要求应用说明第三方处理个人信息的相关情况。
所以团队内部 Disclosure 至少保留:
SDK 名称
主体 / 提供方
使用目的
数据类型
处理方式
是否网络传输
隐私声明来源
业务启用条件
手机诊断页为了可读性只显示:
Remote Configuration SDK
Drive Kit
详细报告里仍然有完整字段。
发布资料不能因为 UI 卡片空间有限,就把真正需要核对的信息删掉。
二十、账号体系还要把“注销入口”纳入审核矩阵
当前 AppGallery 用户隐私规则还明确提到,如果应用提供账号系统,需要让用户能够方便地注销账号,并且注销真正生效。
ReleaseGuard Demo 当前没有账号功能,所以本轮这一项:
NOT_APPLICABLE
但工具已经预留:
accountSystemEnabled
accountDeletionEntry
accountDeletionVerified
一旦业务以后接入账号,发布预检就自动要求补这条链。
这种“按能力动态增加检查项”比所有项目都用同一张固定表更合理。
二十一、隐私报告应该输出“证据位置”
机器判断:
policy mapped=true
还不够。
发布负责人最好能直接看到:
权限声明在哪个文件
隐私政策哪一节
SDK Privacy Statement 哪个版本
AGC 标签是哪一项
所以 Matrix Row 还会保存:
evidence:
module.json5#requestPermissions[1]
policy:
privacy_1.3.0#3.2
sdk:
RemoteConfig-Privacy-2025-09-02
agcTag:
device_information
如果审核被退回,这些证据能很快帮助团队确认:
到底是代码漏了
还是市场资料漏了
二十二、02 最后固定八组异常测试
正常 10/10 之外,我会故意制造:
1 CAMERA reason 与业务不匹配
2 SDK 依赖存在但 Disclosure 缺失
3 SDK 版本升级后仍沿用旧 review 状态
4 本地数据项与 AGC tag 数量相同但内容不同
5 应用内隐私政策 revision 与 AGC 不一致
6 敏感权限在首次启动无场景弹出
7 权限拒绝后无降级路径
8 release Profile 权限集合少于包内声明
每一项都应该得到明确风险码,而不是统一显示:
PRIVACY_ERROR
只有正常链通过、错误链能被准确识别,PRIVACY_READY 才真正有发布价值。
参考资料
- AppGallery Review Guidelines:User Privacy:https://developer.huawei.com/consumer/fr/doc/app/50104-07
- AppGallery Connect:Configuring a Privacy Description:https://developer.huawei.com/consumer/es/doc/app/agc-help-release-app-privacy-desc-0000002313477969
- AppGallery 隐私常见问题:开发者信息与隐私政策一致性:https://developer.huawei.com/consumer/fr/doc/app/FAQ-faq-09
- Remote Configuration SDK Data Security:https://developer.huawei.com/consumer/fr/doc/AppGallery-connect-Guides/agc-remoteconfig-harmonyos-sdksecurity-0000001139007222
- Drive Kit SDK Privacy Statement:https://developer.huawei.com/consumer/en/doc/hmscore-guides/sdk-privacy-statement-0000001670973180
更多推荐




所有评论(0)