rea-reverse

自己的 App 被 Play Protect 拦截?开发者视角的原因排查与正当处理

基于 REA 6.4.0更新于 约 10 分钟读完
本页目录

结论先行:你自己构建、自己分发的应用被 Google Play Protect 拦截或警告,原因几乎都能在 APK 里找到,而且都是你能改的:targetSdk 太旧、申请了 READ_SMS 或无障碍服务这类敏感能力、用调试密钥或公开密钥签名、ZIP 结构不规范。先查清是哪一条,修好构建,固定使用一把发布密钥;确认应用确实干净之后,再用 Google 官方的 Play Protect 申诉表。

本文写给在 Google Play 以外分发 APK 的开发者,比如官网下载、企业内部门户、发给客户的测试包,并且在自己的应用上看到了“已拦截此应用以保护您的设备”、“已拦截有害应用”或者“此应用专为旧版 Android 打造”之类的提示。本文不讲怎么在手机上关掉 Play Protect:那是用户自己的选择,也解决不了你的应用在其他所有人手机上被标记的问题。

读完你会知道:

  • 根据 Google 的开发者指南,Play Protect 有哪几种提示、各自由什么触发
  • 怎么用本站的 APK/AAB 分析与上架体检 检查自己的 APK,附我自己构建的包的真实输出
  • 每条结果对应的正当修法
  • 加壳、加固应该怎么看,为什么会带来误报风险
  • 怎么申诉,申诉表要填什么

只分析和安装你自己构建或已获授权测试的应用,并且只在你能控制的设备上操作。

Play Protect 在安装时看什么

Google 的 Play Protect 开发者指南(页面最后更新于 2026-08-18,我于 2026-10-14 核对)列出了开发者可能遇到的几类提示。和线下分发关系最大的是这几种:

  1. 已拦截应用以保护设备:从“互联网侧载来源”(浏览器、聊天软件、文件管理器)安装的应用,只要声明了 RECEIVE_SMS、READ_SMS、通知监听或无障碍服务,安装就会被拦下。Google 在各地区的公告里把这个功能叫做增强型反诈保护,例如 2026 年 4 月面向马来西亚全部用户上线。Google 没有公布一份完整的市场名单。
  2. 已拦截有害应用:应用命中了恶意软件或移动垃圾软件(MUwS)类别。Google 要求开发者检查自己用到的 API 和权限,确认自己的代码和第三方 SDK 里没有恶意代码,并且使用合法、标准的 APK/ZIP 头。
  3. 欺骗性的无障碍工具:无障碍配置里写了 isAccessibilityTool="true",但应用并不是帮助残障用户的。
  4. 应用兼容性过低:targetSdkVersion 比设备的 API 级别低两级以上。Google 给的例子是:在 Android 13(API 33)上,目标版本低于 API 31 的应用会看到这个警告。
  5. 建议扫描应用 / 发送应用进行安全检查:Play Protect 以前没见过这个应用。Google 明确说,申诉去不掉这个提示。

“有害”的具体分类见 PHA 类别页面:后门、扣费欺诈、跟踪软件、恶意下载器、钓鱼、间谍软件、木马、风险软件等。同一页面也说明,“不常见”的应用并不一定有害。

第 1 步:对自己的 APK 跑一遍线下分发检查

打开 APK/AAB 分析与上架体检,场景选 Play 以外(线下分发) 或 两者都要,把用户实际下载的那个 APK 拖进去。文件只在浏览器里读取,不会上传。

为了给出真实输出,我用 build-tools 36.0.0 里的 aapt2、d8、zipalign 和 apksigner 做了一个小应用 dev.example.ppdemo。第 1 版故意做成反面教材:目标 API 33,申请 RECEIVE_SMS、READ_SMS、SYSTEM_ALERT_WINDOW,带一个 isAccessibilityTool="true" 的无障碍服务和一个通知监听服务,并用主题为 Android 调试证书的密钥签名。按 2026-10-14 的规则、线下分发场景跑分析器核心,结果如下(工具输出保持英文原样):

SIGN-01  high  Signed with an Android debug certificate
   v1 signer: CN=Android Debug,O=Android,C=US — Android SDK debug certificate (SHA-256 4a11a9df…5130983)
SIDE-02  high  Old targetSdk: Play Protect warning on install
   targetSdkVersion=33
   latest Android API level on 2026-10-14: 37
SIDE-03  high  Permissions blocked for sideloaded apps by enhanced fraud protection
   uses-permission android.permission.RECEIVE_SMS
   uses-permission android.permission.READ_SMS
   notification listener service .NotifService
   accessibility service .OtpReaderService
SIDE-04  high  Accessibility service marked as an accessibility tool
   service .OtpReaderService: isAccessibilityTool="true" (res/xml/a11y_tool.xml)
SIDE-06  high  High-risk combination of capabilities
   4 of 5: SYSTEM_ALERT_WINDOW, accessibility service, SMS (READ_SMS, RECEIVE_SMS), notification listener
SIDE-10  high  Android developer verification: what to register
   package: dev.example.ppdemo
   signer SHA-256: 4a11a9df…5130983 (debug certificate)

每一条都能对上 Google 的某种提示。下面是各条规则的准确触发条件,方便你理解通过和不通过分别意味着什么。

规则 级别 触发条件
SIDE-02 高风险 targetSdk 比体检日期当时最新的 Android 版本低两个以上 API 级别(2026-10-14 最新是 37,即低于 35)
SIDE-03 高风险 RECEIVE_SMS、READ_SMS、通知监听服务或无障碍服务
SIDE-04 高风险 无障碍服务的配置里 isAccessibilityTool="true";配置 XML 读不到时为未知
SIDE-06 高风险 同时具备以下三项或以上:SYSTEM_ALERT_WINDOW、无障碍服务、短信权限(READ_SMS、RECEIVE_SMS、SEND_SMS)、设备管理员 receiver、通知监听
SIDE-09 高风险 / 建议 重复条目、中央目录与本地头不一致、不安全路径、加密标志位或未知压缩方式(高风险);归档末尾有多余数据(建议)
SIGN-01 Play 以外为高风险 任一签名者证书的主题 CN 为 “Android Debug”
SIGN-02 Play 以外为高风险 任一签名者证书的 SHA-256 与私钥已公开的密钥一致:AOSP 测试密钥,或 React Native 模板的 debug.keystore
SIDE-10 建议;调试证书或公开密钥时为高风险 始终列出开发者验证需要登记的包名和签名证书 SHA-256

SIDE-02 比 Google 的原话更严格,这是有意的。Google 比较的是设备本身的 API 级别,而工具不知道你的用户用什么手机,所以按最坏情况和最新版本比。目标 33 在 Android 13 手机上没事,到了 Android 17 手机上就会被警告。

SIDE-06 不等于“恶意软件”。规则的修复说明写得很直接:这种组合常见于被 Play Protect 判为有害的应用,所以即使每一项都有正当用途,也容易被重点审查。

第 2 步:逐条修好构建

targetSdk 过旧(SIDE-02):提升 targetSdkVersion,并按该版本的行为变更做回归测试。Google 的目标 API 指南按级别列出了这些变更。目标版本保持在最新或上一个版本,就不会触发这个警告。

短信权限(SIDE-03、SIDE-06):如果读短信只是为了拿验证码,删掉 READ_SMS 和 RECEIVE_SMS,改用 SMS Retriever API 或 SMS User Consent API,两者都不需要短信权限。在我的测试应用上,光这一项就消掉了大部分结果。

无障碍与通知监听(SIDE-03、SIDE-04、SIDE-06):只有它们就是产品核心功能时才保留。除非应用主要面向残障用户,否则把 isAccessibilityTool 设为 false,并在用户启用服务前给出应用内显著披露。确实离不开这些能力的,规则给出的路径是通过应用商店分发并完成 Android 开发者验证,因为反诈保护拦截的正是从浏览器和文件管理器装这类应用的情况。

签名(SIGN-01、SIGN-02):生成一把私有的发布密钥(RSA 2048 位或以上),所有对外版本都用它签,而且不要换。调试密钥每台电脑都不一样,公开密钥则谁都能拿来伪造你应用的“更新”。如果用户手上已经有调试签名的版本,迁移方法见安装包与现有包冲突,因为新密钥签的包没法覆盖旧安装。

ZIP 结构(SIDE-09):用官方工具链重新打包(AGP,或者先 zipalign 再 apksigner),构建完成后不要手动或用第三方工具改归档。

第 2 版目标 API 36,去掉了上面那些权限,用 3072 位发布密钥签名。线下分发场景下只剩一条:

SIDE-10  advice  Android developer verification: what to register
   package: dev.example.ppdemo
   signer SHA-256: 39b9d3743dc22a57099a31b559c990bc6d60b4133317c134ee029d0707ed386a
   note: Registration is not checked here (no network). These are the values the developer console asks for.

干净的构建就该是这个结果,这两个值就是下一步要登记的内容。

第 3 步:开发者验证,加上一把长期不换的密钥

Play Protect 没有公开的信誉查询接口,但有两件事完全在你手里:所有版本都用同一把密钥签名,以及完成 Android 开发者验证。按该页面(2026-10-14 核对)的说法,2026-09-30 起,在巴西、印度尼西亚、新加坡和泰国,运行 Android 7 及以上的认证设备从参与的商店安装应用时开始受到保护,2027 年扩展到全球。只在 Play 以外分发的,在 Android Developer Console 登记;也可以在 Play Console 登记。SIDE-10 列出的包名和证书 SHA-256 就是要填的值,详细步骤见 Android 开发者验证:包名与签名证书 SHA-256。

Google 没有说完成验证就能消除某一条 Play Protect 警告,所以别向用户这样承诺。

加壳与加固:正当,但有误报风险

用商业加壳或加固服务保护自己的代码是正当做法,分析器也这样对待。PROT-01 只是建议级别,识别两类信号:按原生库文件名识别到的商业防护运行库,或者一个弱结构信号,即只有一个很小的 classes.dex,旁边却有大体积的 assets。我的第 3 版带一个 616 字节的 DEX 和一个 3 MB 的资源文件,结果是:

PROT-01  advice  App protection (packer / hardening) identified
   weak structural signal: classes.dex: 616 bytes
   weak structural signal: assets/payload.bin: 3000000 bytes
   note: Packing and hardening are not treated as a problem; this result explains review and false-positive risks.

规则里写明的利弊是:壳的启动代码在结构上和恶意软件的打包器相似,启发式引擎可能误报;带签名自校验的防护在 Play App Signing 下可能失效,因为 Google 会重新签名。正当的应对办法:

  • 选择明确支持 Play App Signing 的方案,或者 Play 版只用 R8。
  • 各个版本始终使用同一个签名证书。
  • Play 版不要从 Google Play 以外下载可执行代码。
  • 发布前把版本提交给主要杀毒厂商报备(通过各家的误报反馈渠道)。
  • 加固后的版本仍被 Play Protect 标记的,按下文申诉,并写明你用的是哪家防护产品。

本文不比较各家壳,也不讨论怎么让壳更不容易被扫描引擎看出来。目标是发一个既受保护、签名和声明也都正确的版本。

第 4 步:确认无误再申诉

Google 的指南要求:先对照指南检查,确认应用不属于移动垃圾软件或 PHA,再对 Play Protect 的判定提出申诉。申诉入口是 Play Protect Appeals Submission Form。2026-10-14 时表单要填:

  • 邮箱(必填)和开发者名称(选填)
  • 应用包名(必填)
  • “SHA256 Hash of the apk of the uploaded file on Virus Total”(必填,即上传到 VirusTotal 的那个 APK 的 SHA-256)
  • 支持申诉的补充说明(必填)

表单写明所有申诉决定都是最终决定,而且不会回复你;Android Enterprise 合作伙伴应走 Partner Escalation Desk。已在 Google Play 上架的应用,则走 Play 的政策申诉流程。

分析器会显示整个文件的 SHA-256(我的第 2 版是 b458e5239a6da5ac15e8949966c97c2a85214a763726814570428c282a79a12d),旁边有“在 VirusTotal 上搜索这个哈希”的链接。这个链接只做搜索。申诉表要的是已上传到 VirusTotal 的文件哈希,所以你得自己把 APK 传上去,而 VirusTotal 会把提交的文件分享给它的社区和合作方。请上传已经公开发布的版本,不要传未发布的版本。上传后核对 VirusTotal 上的哈希和分析器显示的是否一致。

补充说明里写分析人员需要的信息:应用做什么,每个敏感权限为什么需要(或者说明这一版已经删掉),签名证书 SHA-256,用了哪家防护产品,以及用户从哪里下载。

企业与内部应用

如果应用只装在本单位的设备上,通过 managed Google Play 发布私有应用,就完全不走侧载这条路。Google 的说明见 Publish private apps from the Play Console。在注册流程中被拦截的设备策略控制器(DPC),开发者指南给出的办法是通过 Android Enterprise 申请 DPC 审批。

REA 6.4.0 在这里能做什么

REA(morluto 的开源项目)6.4.0 没有任何 Play Protect 或 Play 政策检查。inspect-android-package 读取 Manifest,结果里写着 signature_verification: "not_performed"。在测试设备上,安装尝试后可以用 read-adb-logcat 导出一段有界的日志,用 inspect-adb-package 查看已装版本的安装来源和版本号,见用 REA 读 adb logcat 和 bugreport。写本文时我没有在设备上抓到 Play Protect 拦截的现场,所以这里不展示设备日志。

常见问题

申诉能去掉“建议扫描应用”吗? 不能。Google 的指南写明申诉去不掉这个提示,它针对的是 Play Protect 以前没见过的应用。

我的应用确实需要 READ_SMS,怎么办? 在反诈保护已启用的市场,这类应用从浏览器、聊天软件和文件管理器安装时会被拦截。分析器修复说明给出的路径是:通过应用商店分发,并完成开发者验证。

分析器报告全部通过,Play Protect 就不会警告了吗? 不一定。分析器只读文件,Play Protect 还有自己的扫描和信誉判断,这些从文件里看不到。

给应用加壳违反 Google 的规定吗? 这里没有哪条规则这么说,PROT-01 只是建议。Google Play 禁止的是从 Play 以外下载可执行代码;风险软件的定义是用规避手段展示虚假或不同的功能。保护你自己合法的代码,两者都不是。

下一步