为什么 H5 封装包容易被审核盯上
把已有 H5 站点用 WebView 包一层生成 App,是很多团队快速上架的做法。但审核方看到的不是一个网页,而是一个安装包:它会加载远程内容、申请系统权限、可能跳转到站外。只要这几点里有一处说不清楚,就容易被判定为“功能不完整”“内容与描述不符”或“存在误导”。下面按缓存、外链、权限、壳与内容一致性四块拆开讲。
一、缓存:别让审核看到旧页面
WebView 默认会缓存静态资源,这在正常使用中是优点,在审核场景里却可能变成事故。审核人员打开 App 时,如果命中了旧版本缓存,看到的可能是已经下线的活动页、错误的文案,甚至空白页。
- 版本化入口:首页 URL 带上构建号或版本参数,发版时强制刷新入口,避免首页长期命中旧缓存。
- 区分缓存策略:HTML 主文档用较短缓存或协商缓存,JS/CSS/图片等带 hash 的静态资源可以长缓存。
- 提供清理入口:在设置里放“清除缓存”,并确保清除后能正常重新加载,而不是白屏。
- 离线兜底页:网络异常时展示可读的提示页,而不是 WebView 默认的错误页,后者常被视为功能缺陷。
另外,如果 App 内置了离线包或本地资源包,要保证更新机制可回滚,避免一次错误的热更新把线上壳变成打不开的空壳。
二、外链:把“跳出去”的路径管住
H5 页面里一个普通链接,在浏览器里是正常跳转,在 App 里却可能触发系统浏览器、拉起其他 App,甚至打开支付或下载页面。审核对这类行为通常比较敏感,尤其是涉及外部支付、诱导下载和内容不可控的站点。
- 维护外链白名单,只允许业务确需的域名在应用内打开,其余走系统浏览器并给出提示。
- 拦截 intent://、自定义 scheme 等唤起方式,明确哪些允许、哪些直接丢弃。
- 对 target=_blank 与 window.open 做统一处理,避免出现无法返回的“死页面”。
- 检查页面中是否存在指向应用商店、第三方支付或博彩类站点的链接,这类内容最容易引发审核问询。
如果业务确实需要跳转外部,建议在跳转前给用户一个明确说明,并在返回路径上做好处理。关于分发环节的稳定性,可参考站内的应用分发与上架支持说明。
三、权限申请:按需、可解释、可拒绝
H5 封装 App 常见的权限问题有两类:一是壳本身申请了页面根本用不到的权限;二是页面在用户还没理解场景时就弹出授权框。
- 最小化清单:逐个核对 AndroidManifest 与 Info.plist,删掉相机、通讯录、定位等与当前功能无关的声明。
- 场景内触发:扫码、上传头像、定位门店等操作发生时才申请,而不是启动即弹。
- 说明文案:权限用途描述要具体,写清“用于扫描二维码登录”,而不是笼统的“为了更好的体验”。
- 拒绝后可用:用户拒绝权限时,页面应降级可用,而不是卡死或反复弹窗。
WebView 内的网页通过 JS Bridge 调用原生能力时,同样要在原生侧做一次权限校验,不能默认网页的请求都是可信的。
四、壳与内容一致性:审核看到的就是用户看到的
这是 H5 封装最容易出问题的地方。应用商店的截图、描述、分类,与 App 实际加载的内容必须对得上。常见的不一致包括:
- 商店描述是电商,打开后首页是资讯或活动聚合页;
- 截图展示的是登录后的功能,审核账号却看不到;
- 壳里内置了多个站点入口,实际内容超出申报范围;
- 启动后先展示一个与业务无关的引导页或广告页。
建议在提审前用干净的测试账号完整走一遍首启流程,确认首屏内容、核心功能、付费路径都与申报信息一致。如果内容由服务端动态下发,最好在提审期间锁定版本,避免审核过程中页面被替换。
提审前的自查清单
- 清空缓存后冷启动,首屏能否正常加载;
- 断网状态下是否有可读的提示页;
- 外链是否都在白名单内,跳转后能否返回;
- 权限清单是否最小化,拒绝后功能是否降级可用;
- 商店描述、截图与实际内容是否一致;
- 测试账号能否覆盖核心路径。
把这些点做成发版前的固定检查项,比每次被拒后再回头排查要省事得多。关于壳应用在分发渠道上的注意事项,也可以结合安装包检测与分发建议一起看。