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
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐