准备发布应用时,却在审核阶段被退回。这是很多开发者至少都会遇到一次的门槛。
而且,审核被卡住的原因并不只有崩溃或构建缺陷。权限说明、隐私政策、付费路径、商店元数据、审核备注不足等,实现之外的运营层面问题同样经常成为原因。
本文会按类别整理 App Store 与 Google Play 审核中常见的驳回案例,并从实务角度总结提交前应该确认的重点。
在 Google Play 上,Data safety、广告申报、目标年龄不一致,后续可能引发修改要求甚至下架。即使它不像 App Store 那样常被拿来讨论,申报一致性的重要性是一样的。
:::
类别 6: UGC 与高风险类别
14. 有 UGC,但没有 moderation 路径
如果应用处理用户生成内容,仅仅有发帖功能是不够的。至少最好准备这些路径:
- 举报功能
- 屏蔽功能
- 使用条款
- 联系窗口
- 违规内容处理方针
有 UGC 却看不到防护措施时,审核方更容易担心运营风险。
15. 健康、金融、儿童类别中的说明责任不足
医疗 / 健康、金融 / 投资、儿童向、持续使用位置的应用,会比一般类别被看得更严格。最好预设更高标准去满足准确性、法律合规、没有误解空间的说明以及明确的联系方式。
尤其在这些类别里,“看起来更方便所以写上去”的文案反而可能起反效果。和健康或投资相关的表达,需要避免效果保证、误导或引发过度期待。
实务上,从下面这些角度复查可以减少事故:
- 医疗或健康: 是否避免断言诊断或治疗效果
- 金融: 是否避免保证收益或煽动过高期待
- 儿童向: 外部链接、广告、付费路径是否过强
- 持续位置使用: 是否真的有必要常时获取,是否存在替代手段
在这些类别里,比起加功能,更重要的是确认自己有没有说得过头,以及是否履行了解释责任。
如何解读常见的驳回文案
审核消息通常很短也很抽象,直接照字面理解时,很难判断到底该修什么。实务上,把它换成下面这种理解方式,会更容易行动。
| 审核消息的倾向 | 实际被怀疑的内容 | 第一件要做的事 |
|---|---|---|
App Completeness |
未完成、崩溃、路径断裂 | 录制启动视频,找出不能点击的按钮和空页面 |
Your app requests access... |
不必要权限、说明不足 | 把该权限和需要它的画面及说明文做 1 对 1 对应 |
Metadata does not reflect... |
截图或说明文不一致 | 并排核对商店说明、图片和实现差异 |
Use in-app purchase |
数字付费被引导到外部 | 先整理自己卖的是什么,再改回 IAP 前提 |
Target API level |
Android 提交要求未达标 | 更新 target SDK 与依赖库后重新测试 |
Data safety form is inaccurate |
申报与 SDK 实现不一致 | 盘点 SDK 并更新 Console 申报 |
这里的关键,是把审核文案当成规格说明来读。看似抽象,但大多数问题都能归类到:未完成、说明不足、或申报不一致。
Google Play 中容易忽略的项目
新 personal account 的首次发布要求
如果你是第一次面向 Google Play 发布,这里尤其重要。新创建的 personal developer account,除了应用内容外,还存在进入 production 的 account 级要求。
代表性的有这两项:
- closed test 中持续参加的 tester 需要达到 12 人以上
- 需要使用 Play Console mobile app 完成 Android 真机 device verification
这与其说是传统的“驳回邮件”,不如说是 Play Console 内部阻止你进入 production 的关卡。也就是说,即使应用本身已经完成,只要 account 侧条件没满足,就仍然无法发布。
首次发布常见的卡点包括:
- tester 数量够了,但没有满足连续 14 天 opt-in 条件
- tester 只是加入了,但实际使用或反馈不足
- account owner 还没完成 device verification
- 误以为 internal test 就足够,从而漏掉 closed test 条件
如果是首次发布,更安全的做法是和实现验证并行,尽早把这些要求解决掉。
target SDK 跟进不足
Google Play 对 target API level 的要求会持续更新。真正需要建立的是一种习惯:在提交当下去 Play Console 确认最新要求,而不是依赖文章撰写时的数字。
这里最容易混淆的是 targetSdkVersion 和 minSdkVersion 的差别。
targetSdkVersion: 表示对新 Android 行为支持到什么程度minSdkVersion: 表示你支持到多旧的 Android 版本
换句话说,即使你没有提高 minSdkVersion,Google Play 也仍然可能仅因为 targetSdkVersion 落后于提交要求而阻止发布。
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
targetSdkVersion rootProject.ext.targetSdkVersion
minSdkVersion 24
}
}
对应方案的重点,不是只改数字就结束。提高 target SDK 后,权限模型、后台限制、通知行为、foreground service、文件访问等都可能变化。更新时最好一起确认这些:
- Android Gradle Plugin 与依赖库的兼容情况
- 权限弹窗行为差异
- 通知与后台处理限制
- 主要目标设备上的真机测试
manifest 中仍残留危险权限
如果 manifest 里残留了未使用的危险权限,依然会产生解释责任。尤其是 CONTACTS、CALL_LOG、SMS、READ_PHONE_STATE 等权限,更要谨慎复查。
<!-- 不要声明不会使用的权限 -->
<!-- <uses-permission android:name="android.permission.READ_CONTACTS" /> -->
<!-- <uses-permission android:name="android.permission.READ_CALL_LOG" /> -->
Data safety 与实现不一致
已经加入 Analytics SDK 或广告 SDK,但 Console 侧申报还是旧的,这种情况比想象中更常见。每次替换 SDK 时,都应把 Data safety 视作必须一起更新的对象。
Data safety 是 Google Play 上用来申报“应用收集 / 共享哪些数据,以及这些数据用于什么”的栏目。Apple 侧的 App Privacy 逻辑相近,只要和实现不一致,就会削弱信任。
最安全的做法,是不要凭感觉填写,而是老老实实盘点:
- 列出已经接入的 SDK
- 确认每个 SDK 处理的数据类型
- 同时盘点自家 API 发送的数据
- 与 Play Console / App Store Connect 上的申报逐项比对
- 如果内容变了,也同步更新隐私政策
在“真正使用的瞬间”再请求权限
应用一启动就连续弹出多个权限对话框,这种设计很容易给用户和 reviewer 都留下不好的印象。
更好的方针是:
- 用户进入对应功能时再请求权限
- 在弹窗前加一段简短的 pre-permission 说明
- 对 deny 的情况准备替代路径
这不仅是审核对策,也能提升权限同意率。
申请备注里应该写什么
审核备注栏常常被低估,但它是减少 reviewer 犹豫的重要位置。尤其对于必须登录的应用、依赖权限的应用、连接外部设备的应用,效果更明显。
适合写进去的内容:
- demo account 信息
- 到达主要功能的步骤
- 会使用权限的画面说明
- 如果需要 2FA 或特定角色时的补充说明
- 如果依赖外部服务器或设备时的补充说明
简短模板示例:
审核账号:
Email: reviewer-demo@example.com
Password: xxxxxxxx
主要测试流程:
1. 使用审核账号登录
2. 打开 Map 标签页以测试位置权限
3. 打开 Settings > Subscription 以确认取消订阅说明
被驳回后的应对方针
被驳回时,最重要的不是情绪化反驳,而是准确给出问题分类。
基本顺序如下:
- 原样重新阅读指出的问题
- 确认复现条件
- 分类为实现缺陷、说明不足、或申报错误
- 必要时用截图或视频补充
即使看起来真的是误判,通常也是先补齐说明更快。把 appeal 视为最后手段,会更符合实务。
实际回复时,比起很长的辩解,简短明确地写出“做了什么修改”通常更容易通过。
感谢审核。
我们将问题识别为 [implementation / metadata / clarification]。
我们做了以下修改:
1. 修复了 [issue]
2. 更新了 [metadata or review notes]
3. 补充了 [account / explanation / screenshot]
验证方式:
1. 使用审核账号登录
2. 打开 [screen name]
3. 点击 [action]
如有需要,我们可以提供额外截图或录屏。
如果用中文整理,其实只要三点就够了:原因、修正内容、确认步骤。越是在审核中拖得久的团队,这三点越容易混在一起,导致沟通困难。
提交前 48 小时要做什么
发布前总会很想再加一个功能,但如果目标是提升审核通过率,临近提交时把时间花在确认上,通常比继续实现更有效。
48 小时前
- 复查商店说明文、截图、年龄评级、Data safety / App Privacy
- 盘点当前使用的 SDK 与权限列表
- 准备 reviewer 用账号和审核备注
24 小时前
- 在最新 iPhone OS、前一个 iOS 版本以及多台 Android 设备上确认启动行为
- 测试飞行模式、低速网络、首次安装状态
- 端到端检查付费、登录、权限请求、注销 / 删除账号路径
6 小时前
- 最后再看一次截图与实际应用是否仍一致
- 确认商店申报与 SDK 配置没有偏差
- 在审核备注中写清到达主要功能的步骤和必要补充
即使只是每次都完整跑一遍这套 48 小时流程,也会很大程度上降低驳回率。
防止再次发生的运营方式
即使已经通过一次审核,只要新增功能或替换 SDK,同样的问题仍然很容易再次出现。无论是个人开发还是团队开发,下面这些做法都能减少事故:
- 只要新增 SDK,就把权限、Data safety、App Privacy 的更新视为同一组工作
- 商店说明文里只写已经实现的功能
- 新增权限时,在 PR 中同时确认使用画面和说明文
- 把发布前检查清单做成 issue 或模板,反复复用
- 把驳回文案和对应处理记录下来,复用到下一次审核备注里
最大的长期收益,是不要再把审核应对当成每次都临场现想的工作。
提交前检查清单
按提交平台拆开成可直接使用的形式,更容易发现遗漏。即使是共通项,也分别放进各自的表里。
App Store 提交前检查清单
| 视角 | 确认项 | 为什么重要 |
|---|---|---|
| 完成度 | [ ] 在最新 iOS 和前一个主要版本中,首次启动、空数据、低速网络下也不会崩溃 | 防止 App Completeness 或崩溃指摘 |
| 审核路径 | [ ] 已在审核备注中写明 reviewer 账号、到达步骤,以及必要时的 2FA 步骤 | 仅仅因为 reviewer 无法验证就会被退回 |
| 权限 | [ ] Info.plist 中的说明文已绑定到具体功能名 |
避免权限说明不足 |
| 隐私 | [ ] Privacy Policy URL 已公开,并已配置到 App Store Connect | 数据收集型应用的基础要求 |
| 申报一致性 | [ ] App Privacy 申报内容与当前 SDK 配置一致 | 避免申报不一致 |
| 付费 | [ ] 数字内容或应用功能销售使用 IAP | 避免引导外部支付 |
| 订阅 | [ ] 付费页可读出套餐名、期间、总金额、自动续订、试用后价格、取消方式 | 避免订阅说明不足 |
| 订阅者路径 | [ ] 有 Terms of Service / Privacy Policy 链接,以及 restore purchases 或 sign in 路径 | 避免既有订阅者路径不足 |
| ATT | [ ] 若使用 IDFA 或 tracking,ATT 与 App Privacy 已对齐 | 防止 tracking 相关退回 |
| 元数据 | [ ] 截图、说明文、子标题与当前实现一致 | 避免 metadata mismatch |
Google Play 提交前检查清单
| 视角 | 确认项 | 为什么重要 |
|---|---|---|
| 首次发布要求 | [ ] 如果是新的 personal account,已满足 12 人以上、14 天以上的 closed test 条件 | 避免无法进入 production access 的阻断 |
| 账号确认 | [ ] 如果是新的 developer account,account owner 已完成 Android 真机 device verification | 避免发布前的 account gate |
| 完成度 | [ ] 已在多台 Android 设备上确认首次启动、离线、空数据时的行为 | 减少实现缺陷与 pre-review check 问题 |
| 技术要求 | [ ] targetSdkVersion 满足提交当下的要求 |
避免提交要求未达标 |
| 分发设置 | [ ] 已确认包含 64-bit 支持的构建设置与依赖库兼容性 | 避免分发时的技术要求违规 |
| 权限 | [ ] 只保留真正必要的危险权限,并能说明必要性 | 避免 permissions 与功能不一致 |
| 隐私 | [ ] Privacy Policy 已公开,且与 Play Console 设置一致 | 避免数据处理说明不足 |
| 申报一致性 | [ ] Data safety、广告申报、年龄设置与当前 SDK 配置一致 | 避免 Console 侧申报不一致 |
| 登录路径 | [ ] 已为 reviewer 准备能到达主要功能的账号或步骤 | 避免因无法真机验证而被退回 |
| 付费 | [ ] 订阅或付费路径的价格、续订条件、取消方式清晰易懂 | 避免误导性的付费 UI |
| 商店信息 | [ ] 商店说明文、截图、类别设置与实现一致 | 避免 listing mismatch |
| SDK 运营 | [ ] SDK 的增删变更已反映到 Data safety 与 permissions | 避免后续补正要求 |
总结
应用审核最容易被卡住的,往往不是单纯 bug,而是 实现与说明不一致 以及 运营准备不足。
尤其重要的是下面 4 点:
- reviewer 能毫无迷惑地确认主要功能
- 权限与数据收集理由被具体说明
- 付费规则与商店申报已经正确对齐
- 商店元数据与实际实现一致
越接近发布,越容易想继续加功能。但如果目标是提升审核通过率,把最后一天用于跑完检查清单,通常更有效。
参考链接
- App Store Review Guidelines
- Auto-renewable subscriptions
- Google Play Policy Center
- Human Interface Guidelines
- In-App Purchase (Human Interface Guidelines)
- Distributing reader apps with a link to your website
- App testing requirements for new personal developer accounts
- Device verification requirements for new developer accounts
- Target API level requirements for Google Play apps
- App Tracking Transparency
- 即便存在 Reader App 例外,适用类别和实现条件也相当有限
如果你不确定是否应该使用 IAP,最容易判断的标准就是:它是不是在应用内被消费的数字价值。
- 更偏向 IAP 的例子: 去广告、高级功能、游戏货币、文章无限阅读、视频无限观看
- 通常可用外部支付的例子: 实体商品、叫车、线下课程、餐饮配送、酒店预订
如果已经引导到外部支付并因此被卡住,通常需要往下面其中一个方向调整:
- 改成以 IAP 为前提的付费设计
- 认真确认自己是否真的符合 Reader App 条件
- 把数字商品与实体服务拆开,重新整理应用内路径
9. 订阅说明不充分
在订阅场景里,如果价格、续订周期、自动续订、取消路径表述模糊,就会从用户保护角度被认为不够完善。
至少应在付费页或商店说明中明确这些内容:
- 能看出套餐名称、时长和提供内容
- 清楚展示总收费金额;如果是年费,最醒目地展示年费总额
- 能看出续订周期以及它是自动续订
- 能看出免费试用结束后的正常价格
- 有 Terms of Service 和 Privacy Policy 的链接
- 为已有订阅用户提供 sign in 或 restore purchases 路径
- 能理解如何取消订阅
常见失败模式是:把按月折算的价格放得很大,却让真实扣费金额和续订条件变得难懂。对于年费方案,更安全的做法是先清楚显示年总额,再在下面辅助展示月均价格。
检查订阅画面时,按这些要素来审视通常最有效:
- 套餐名称
- 扣费时机
- 总收费金额
- 免费试用后的正常价格
- 恢复购买路径
- 服务条款与隐私政策
- 管理画面或取消路径
例如,像“免费 7 天,之后按每年 7,200 日元自动续订”这种一句话就说清试用后会发生什么的表达,在审核里更不容易被误解。
另外,为了让购买画面更不容易在审核中被卡住,最好直接在画面内回答用户最容易困惑的问题:
- 当前选中的是哪个套餐
- 现在会扣多少钱
- 免费期结束后会收多少钱
- 最晚何时取消才能避免下一次扣费
- 已有订阅用户可以从哪里恢复
// 仅靠 React Native 无法直接打开 StoreKit 提供的 system-provided UI,
// 这是在无法桥接 iOS 原生实现时的 fallback 示例。
import { Linking, Text, TouchableOpacity } from 'react-native'
function SubscriptionSettings() {
return (
<TouchableOpacity
onPress={() => Linking.openURL('https://apps.apple.com/account/subscriptions')}
>
<Text>管理订阅</Text>
</TouchableOpacity>
)
}
如果可以做 iOS 原生实现,更自然的做法是使用 Apple 提供的 showManageSubscriptions(in:) 打开 system-provided management UI。
10. 过度扩大解释 Reader App 例外
Reader App 例外看起来很方便,但适用范围相当有限。主功能必须确实属于 杂志、报纸、书籍、音频、音乐、视频 之一,并且前提是应用用于查看或播放在外部购买好的内容或订阅。
此外,如果要显示外部网站的账号创建或管理链接,还需要 External Link Account Entitlement。已经在 iOS / iPadOS / tvOS 上提供 IAP 的应用,不属于该 entitlement 的适用对象,因此“因为是 Reader App,所以可以自由引导到外部付费”这种理解是错误的。
视频、音乐、书籍这类消费型内容,与应用功能或游戏内货币的处理方式并不相同。如果在自己应用属于哪个类别这件事上含糊不清,就很容易在审核时出现判断摇摆。
如果拿不准,最好先整理“你卖的是内容还是功能”“购买路径在哪里”,并在商店说明和审核备注里补充说明。
实务上,提交前可以用下面 3 个 Yes / No 问题快速判断:
- 主功能是否确实是提供杂志、报纸、书籍、音频、音乐或视频
- 应用结构是否以查看外部已购买内容为中心
- iOS 端是否没有提供 IAP
这 3 点里只要有任何一点含糊,就更安全的做法是不以 Reader App 例外为前提来设计。
类别 4: 设计与体验质量
11. UI 与平台预期偏差过大
完全自定义的导航体系、缺失返回路径、对比度过低导致难读,都会降低应用的可用性评价。在审核中,通常比起追求视觉上的独特性,更应该优先保证符合平台预期的可操作性。
12. 看起来只是包了一层 WebView
如果应用本质上只是把网站原样显示出来,就可能被认为原生体验价值不足。
危险模式:
- 几乎整个画面都是 WebView
- 没有原生特有功能
- 离线时什么也做不了
- 没有设备联动、通知等“作为应用才有”的价值
想避免看起来像单纯 wrapper,最好明确体现设备整合带来的价值,例如分享、通知、相机、本地保存、离线 UX 等。
WebView 本身不是问题。问题在于:你提交的是原生应用,但内容看起来几乎就是网站原样搬进来。如果要使用 WebView,至少最好在以下某一个方面体现原生端的价值:
- 原生导航或设置画面
- 分享、通知、相机、文件保存等设备功能
- 离线时的说明或缓存显示
- Web 版里没有的应用专属交互体验
13. 广告或付费路径过于激进
如果广告比内容更显眼、布局会诱发误触、或者难以关闭的 interstitial 使用过多,不仅会影响审核,也会直接拉低评价。可以有变现路径,但需要用真机确认它们 没有破坏整体体验。
类别 5: 商店元数据与申报信息
审核看的不只是应用本体,也包括商店说明文和申报内容。这里如果和实际情况不一致,即使实现本身没问题,也可能被卡住。
值得复查的项目:
- 截图
- 应用说明文
- 子标题
- 年龄评级
- App Privacy / Data safety
- 是否包含广告的申报
尤其危险的是,在说明文里写了并未实现的功能。提前宣传未来计划中的功能,也同样不安全。
类别 6: UGC 与高风险类别
14. 有 UGC,但没有 moderation 路径
如果应用处理用户生成内容,仅仅有发帖功能是不够的。至少最好准备这些路径:
- 举报功能
- 屏蔽功能
- 使用条款
- 联系窗口
- 违规内容处理方针
有 UGC 却看不到防护措施时,审核方更容易担心运营风险。
15. 健康、金融、儿童类别中的说明责任不足
医疗 / 健康、金融 / 投资、儿童向、持续使用位置的应用,会比一般类别被看得更严格。最好预设更高标准去满足准确性、法律合规、没有误解空间的说明以及明确的联系方式。
尤其在这些类别里,“看起来更方便所以写上去”的文案反而可能起反效果。和健康或投资相关的表达,需要避免效果保证、误导或引发过度期待。
实务上,从下面这些角度复查可以减少事故:
- 医疗或健康: 是否避免断言诊断或治疗效果
- 金融: 是否避免保证收益或煽动过高期待
- 儿童向: 外部链接、广告、付费路径是否过强
- 持续位置使用: 是否真的有必要常时获取,是否存在替代手段
在这些类别里,比起加功能,更重要的是确认自己有没有说得过头,以及是否履行了解释责任。
如何解读常见的驳回文案
审核消息通常很短也很抽象,直接照字面理解时,很难判断到底该修什么。实务上,把它换成下面这种理解方式,会更容易行动。
| 审核消息的倾向 | 实际被怀疑的内容 | 第一件要做的事 |
|---|---|---|
App Completeness |
未完成、崩溃、路径断裂 | 录制启动视频,找出不能点击的按钮和空页面 |
Your app requests access... |
不必要权限、说明不足 | 把该权限和需要它的画面及说明文做 1 对 1 对应 |
Metadata does not reflect... |
截图或说明文不一致 | 并排核对商店说明、图片和实现差异 |
Use in-app purchase |
数字付费被引导到外部 | 先整理自己卖的是什么,再改回 IAP 前提 |
Target API level |
Android 提交要求未达标 | 更新 target SDK 与依赖库后重新测试 |
Data safety form is inaccurate |
申报与 SDK 实现不一致 | 盘点 SDK 并更新 Console 申报 |
这里的关键,是把审核文案当成规格说明来读。看似抽象,但大多数问题都能归类到:未完成、说明不足、或申报不一致。
Google Play 中容易忽略的项目
新 personal account 的首次发布要求
如果你是第一次面向 Google Play 发布,这里尤其重要。新创建的 personal developer account,除了应用内容外,还存在进入 production 的 account 级要求。
代表性的有这两项:
- closed test 中持续参加的 tester 需要达到 12 人以上
- 需要使用 Play Console mobile app 完成 Android 真机 device verification
这与其说是传统的“驳回邮件”,不如说是 Play Console 内部阻止你进入 production 的关卡。也就是说,即使应用本身已经完成,只要 account 侧条件没满足,就仍然无法发布。
首次发布常见的卡点包括:
- tester 数量够了,但没有满足连续 14 天 opt-in 条件
- tester 只是加入了,但实际使用或反馈不足
- account owner 还没完成 device verification
- 误以为 internal test 就足够,从而漏掉 closed test 条件
如果是首次发布,更安全的做法是和实现验证并行,尽早把这些要求解决掉。
target SDK 跟进不足
Google Play 对 target API level 的要求会持续更新。真正需要建立的是一种习惯:在提交当下去 Play Console 确认最新要求,而不是依赖文章撰写时的数字。
这里最容易混淆的是 targetSdkVersion 和 minSdkVersion 的差别。
targetSdkVersion: 表示对新 Android 行为支持到什么程度minSdkVersion: 表示你支持到多旧的 Android 版本
换句话说,即使你没有提高 minSdkVersion,Google Play 也仍然可能仅因为 targetSdkVersion 落后于提交要求而阻止发布。
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
targetSdkVersion rootProject.ext.targetSdkVersion
minSdkVersion 24
}
}
对应方案的重点,不是只改数字就结束。提高 target SDK 后,权限模型、后台限制、通知行为、foreground service、文件访问等都可能变化。更新时最好一起确认这些:
- Android Gradle Plugin 与依赖库的兼容情况
- 权限弹窗行为差异
- 通知与后台处理限制
- 主要目标设备上的真机测试
manifest 中仍残留危险权限
如果 manifest 里残留了未使用的危险权限,依然会产生解释责任。尤其是 CONTACTS、CALL_LOG、SMS、READ_PHONE_STATE 等权限,更要谨慎复查。
<!-- 不要声明不会使用的权限 -->
<!-- <uses-permission android:name="android.permission.READ_CONTACTS" /> -->
<!-- <uses-permission android:name="android.permission.READ_CALL_LOG" /> -->
Data safety 与实现不一致
已经加入 Analytics SDK 或广告 SDK,但 Console 侧申报还是旧的,这种情况比想象中更常见。每次替换 SDK 时,都应把 Data safety 视作必须一起更新的对象。
Data safety 是 Google Play 上用来申报“应用收集 / 共享哪些数据,以及这些数据用于什么”的栏目。Apple 侧的 App Privacy 逻辑相近,只要和实现不一致,就会削弱信任。
最安全的做法,是不要凭感觉填写,而是老老实实盘点:
- 列出已经接入的 SDK
- 确认每个 SDK 处理的数据类型
- 同时盘点自家 API 发送的数据
- 与 Play Console / App Store Connect 上的申报逐项比对
- 如果内容变了,也同步更新隐私政策
在“真正使用的瞬间”再请求权限
应用一启动就连续弹出多个权限对话框,这种设计很容易给用户和 reviewer 都留下不好的印象。
更好的方针是:
- 用户进入对应功能时再请求权限
- 在弹窗前加一段简短的 pre-permission 说明
- 对 deny 的情况准备替代路径
这不仅是审核对策,也能提升权限同意率。
申请备注里应该写什么
审核备注栏常常被低估,但它是减少 reviewer 犹豫的重要位置。尤其对于必须登录的应用、依赖权限的应用、连接外部设备的应用,效果更明显。
适合写进去的内容:
- demo account 信息
- 到达主要功能的步骤
- 会使用权限的画面说明
- 如果需要 2FA 或特定角色时的补充说明
- 如果依赖外部服务器或设备时的补充说明
简短模板示例:
审核账号:
Email: reviewer-demo@example.com
Password: xxxxxxxx
主要测试流程:
1. 使用审核账号登录
2. 打开 Map 标签页以测试位置权限
3. 打开 Settings > Subscription 以确认取消订阅说明
被驳回后的应对方针
被驳回时,最重要的不是情绪化反驳,而是准确给出问题分类。
基本顺序如下:
- 原样重新阅读指出的问题
- 确认复现条件
- 分类为实现缺陷、说明不足、或申报错误
- 必要时用截图或视频补充
即使看起来真的是误判,通常也是先补齐说明更快。把 appeal 视为最后手段,会更符合实务。
实际回复时,比起很长的辩解,简短明确地写出“做了什么修改”通常更容易通过。
感谢审核。
我们将问题识别为 [implementation / metadata / clarification]。
我们做了以下修改:
1. 修复了 [issue]
2. 更新了 [metadata or review notes]
3. 补充了 [account / explanation / screenshot]
验证方式:
1. 使用审核账号登录
2. 打开 [screen name]
3. 点击 [action]
如有需要,我们可以提供额外截图或录屏。
如果用中文整理,其实只要三点就够了:原因、修正内容、确认步骤。越是在审核中拖得久的团队,这三点越容易混在一起,导致沟通困难。
提交前 48 小时要做什么
发布前总会很想再加一个功能,但如果目标是提升审核通过率,临近提交时把时间花在确认上,通常比继续实现更有效。
48 小时前
- 复查商店说明文、截图、年龄评级、Data safety / App Privacy
- 盘点当前使用的 SDK 与权限列表
- 准备 reviewer 用账号和审核备注
24 小时前
- 在最新 iPhone OS、前一个 iOS 版本以及多台 Android 设备上确认启动行为
- 测试飞行模式、低速网络、首次安装状态
- 端到端检查付费、登录、权限请求、注销 / 删除账号路径
6 小时前
- 最后再看一次截图与实际应用是否仍一致
- 确认商店申报与 SDK 配置没有偏差
- 在审核备注中写清到达主要功能的步骤和必要补充
即使只是每次都完整跑一遍这套 48 小时流程,也会很大程度上降低驳回率。
防止再次发生的运营方式
即使已经通过一次审核,只要新增功能或替换 SDK,同样的问题仍然很容易再次出现。无论是个人开发还是团队开发,下面这些做法都能减少事故:
- 只要新增 SDK,就把权限、Data safety、App Privacy 的更新视为同一组工作
- 商店说明文里只写已经实现的功能
- 新增权限时,在 PR 中同时确认使用画面和说明文
- 把发布前检查清单做成 issue 或模板,反复复用
- 把驳回文案和对应处理记录下来,复用到下一次审核备注里
最大的长期收益,是不要再把审核应对当成每次都临场现想的工作。
提交前检查清单
按提交平台拆开成可直接使用的形式,更容易发现遗漏。即使是共通项,也分别放进各自的表里。
App Store 提交前检查清单
| 视角 | 确认项 | 为什么重要 |
|---|---|---|
| 完成度 | [ ] 在最新 iOS 和前一个主要版本中,首次启动、空数据、低速网络下也不会崩溃 | 防止 App Completeness 或崩溃指摘 |
| 审核路径 | [ ] 已在审核备注中写明 reviewer 账号、到达步骤,以及必要时的 2FA 步骤 | 仅仅因为 reviewer 无法验证就会被退回 |
| 权限 | [ ] Info.plist 中的说明文已绑定到具体功能名 |
避免权限说明不足 |
| 隐私 | [ ] Privacy Policy URL 已公开,并已配置到 App Store Connect | 数据收集型应用的基础要求 |
| 申报一致性 | [ ] App Privacy 申报内容与当前 SDK 配置一致 | 避免申报不一致 |
| 付费 | [ ] 数字内容或应用功能销售使用 IAP | 避免引导外部支付 |
| 订阅 | [ ] 付费页可读出套餐名、期间、总金额、自动续订、试用后价格、取消方式 | 避免订阅说明不足 |
| 订阅者路径 | [ ] 有 Terms of Service / Privacy Policy 链接,以及 restore purchases 或 sign in 路径 | 避免既有订阅者路径不足 |
| ATT | [ ] 若使用 IDFA 或 tracking,ATT 与 App Privacy 已对齐 | 防止 tracking 相关退回 |
| 元数据 | [ ] 截图、说明文、子标题与当前实现一致 | 避免 metadata mismatch |
Google Play 提交前检查清单
| 视角 | 确认项 | 为什么重要 |
|---|---|---|
| 首次发布要求 | [ ] 如果是新的 personal account,已满足 12 人以上、14 天以上的 closed test 条件 | 避免无法进入 production access 的阻断 |
| 账号确认 | [ ] 如果是新的 developer account,account owner 已完成 Android 真机 device verification | 避免发布前的 account gate |
| 完成度 | [ ] 已在多台 Android 设备上确认首次启动、离线、空数据时的行为 | 减少实现缺陷与 pre-review check 问题 |
| 技术要求 | [ ] targetSdkVersion 满足提交当下的要求 |
避免提交要求未达标 |
| 分发设置 | [ ] 已确认包含 64-bit 支持的构建设置与依赖库兼容性 | 避免分发时的技术要求违规 |
| 权限 | [ ] 只保留真正必要的危险权限,并能说明必要性 | 避免 permissions 与功能不一致 |
| 隐私 | [ ] Privacy Policy 已公开,且与 Play Console 设置一致 | 避免数据处理说明不足 |
| 申报一致性 | [ ] Data safety、广告申报、年龄设置与当前 SDK 配置一致 | 避免 Console 侧申报不一致 |
| 登录路径 | [ ] 已为 reviewer 准备能到达主要功能的账号或步骤 | 避免因无法真机验证而被退回 |
| 付费 | [ ] 订阅或付费路径的价格、续订条件、取消方式清晰易懂 | 避免误导性的付费 UI |
| 商店信息 | [ ] 商店说明文、截图、类别设置与实现一致 | 避免 listing mismatch |
| SDK 运营 | [ ] SDK 的增删变更已反映到 Data safety 与 permissions | 避免后续补正要求 |
总结
应用审核最容易被卡住的,往往不是单纯 bug,而是 实现与说明不一致 以及 运营准备不足。
尤其重要的是下面 4 点:
- reviewer 能毫无迷惑地确认主要功能
- 权限与数据收集理由被具体说明
- 付费规则与商店申报已经正确对齐
- 商店元数据与实际实现一致
越接近发布,越容易想继续加功能。但如果目标是提升审核通过率,把最后一天用于跑完检查清单,通常更有效。
参考链接
- App Store Review Guidelines
- Auto-renewable subscriptions
- Google Play Policy Center
- Human Interface Guidelines
- In-App Purchase (Human Interface Guidelines)
- Distributing reader apps with a link to your website
- App testing requirements for new personal developer accounts
- Device verification requirements for new developer accounts
- Target API level requirements for Google Play apps
- App Tracking Transparency
