为什么排查顺序比排查项更重要
Play Protect 的风险提示往往只给一个笼统结论,不会告诉你具体命中哪条规则。此时如果直接做全量混淆或加固,既可能掩盖问题,也会让后续复现变难。更有效的做法是按“影响面从大到小、改动成本从低到高”排序:先查那些一旦命中就几乎必然被判风险的项,再查需要抓包或对比签名才能确认的项。
下面这条顺序适合大多数被提示风险的商业 App,也适合 H5 封装壳应用。每一步都建议留下记录,方便后续向渠道或客户解释。
第一步:权限声明与敏感 API 的实际调用
先打开合并后的 AndroidManifest,而不是只看主模块的清单。重点核对三类:
- 高危权限是否真的需要:短信读取、通话状态、后台定位、无障碍服务、悬浮窗、安装未知应用等。壳应用尤其容易因为集成了推送或统计 SDK 被静默合并进这些权限。
- 权限与功能是否对得上:一个工具类 App 申请通讯录权限,即使代码里从未调用,也会显著抬高风险评分。
- 敏感 API 的调用点:用静态扫描确认是否存在读取设备标识、剪贴板、已安装应用列表等行为,并确认是否在用户无感知时执行。
处理原则是先删后解释:能删的权限直接删,确实需要的补上运行时申请与用途说明。权限问题通常改动最小、收益最大,应放在最前面。
第二步:第三方 SDK 与依赖版本
大量风险提示来自过时或来源不明的 SDK。排查时不要只看 build.gradle 的顶层依赖,要拉出完整依赖树,确认实际参与打包的版本。
- 列出所有含广告、统计、推送、热更新、动态加载能力的 SDK。
- 核对每个 SDK 的官方最新版本,优先升级那些长期未维护的。
- 检查是否存在从非官方仓库引入的 aar 或 jar,这类文件最容易夹带额外行为。
- 确认没有在运行时下载并执行代码的逻辑,动态加载是风险提示的常见触发点。
如果业务上必须保留某个老旧 SDK,至少要在发布说明里记录原因,并确认它不会在后台自启动或频繁上报。
第三步:网络传输与明文流量
传输层问题不会直接等于“病毒”,但会明显拉低安全评估。检查项包括:
- 是否仍开启全局明文流量(usesCleartextTraffic 为 true),以及是否有域名确实走 HTTP。
- 是否存在自签名证书或关闭证书校验的代码,这类写法在 H5 壳中很常见。
- WebView 加载的外链是否限定在白名单域名,是否允许任意 URL 跳转。
- 下载类功能是否校验文件来源与完整性,避免成为分发通道。
建议用抓包工具跑一遍主流程,确认没有意外的第三方上报域名。壳应用还要特别检查前端页面里写死的接口地址是否仍是测试环境。
第四步:签名完整性与二次打包痕迹
最后再查签名,因为这一步通常需要拿到原始包对比。重点看:
- 签名证书是否为团队正式证书,是否使用了调试证书或来源不明的证书。
- APK 是否被重新签名,v1/v2/v3 签名方案是否齐全。
- 包内是否存在异常新增的 dex、so 或资源文件,尤其是体积突然增大的情况。
- 是否有完整性校验逻辑,能否在启动时发现被篡改的包体。
如果确认包体被二次打包,问题就不在代码层,而应转向分发渠道与下载链路排查。关于混淆与完整性校验的边界,可以参考我们此前对 APK 加固与混淆的区别 的说明。
把排查结果变成可复用的记录
每次处理完建议固定输出四项内容:命中的具体项、修改前后的包体对比、复现步骤、以及回归验证方式。这样下次再遇到同类提示,可以直接从历史记录里定位,而不是从头再查一遍。若团队需要把安全整改纳入交付流程,可以在 关于我们 页面了解我们的服务范围与协作方式。
最后提醒一点:Play Protect 的判定会随版本和样本库变化,任何排查结论都应以当前实际包体和官方文档为准,不要依赖未经证实的“内部规则”说法。