F-Droid 在 7 月 1 日的博文里把 Google 的 Android Developer Verifier,也就是 ADV,称为“自身传播的恶意软件”。这个说法很重,但它指向的技术问题并不玄学:当 Android 设备上的应用安装路径被一个可远程激活、可集中决策的验证系统接管时,谁来决定一个开发者、一个应用商店、一个 APK 是否“可信”?
这件事对 Android 开发者和发行方很现实。它不只是 F-Droid 与 Google 的口水仗,而是关系到 sideload、第三方应用商店、开源应用分发、企业内部分发,以及用户是否还能在自己的设备上安装自己选择的软件。
争议点不是“安全”,而是“谁拥有开关”
从摘要看,F-Droid 的核心指控是:ADV 已经存在于 Android 8 及以上设备中,并可能在全球大量设备上静默等待远程激活。F-Droid 用“病毒”这样的词,是在强调它认为该组件具备三个危险特征:预装、静默、远程控制。
安全验证本身并不罕见。操作系统检查签名、应用商店扫描恶意代码、企业 MDM 限制安装来源,这些都是常规手段。争议在于,如果一个系统级验证器可以在用户安装应用时介入,并且规则由平台方远程下发,那么它就不只是“提示风险”,而可能变成“阻断分发”。
对开源应用商店来说,这尤其敏感。F-Droid 的分发模式依赖可复现构建、公开源码、第三方仓库和用户主动选择。如果平台验证器把“非 Google Play 路径”天然视为高风险,或者要求开发者接受平台方身份验证,那么开源生态的入口就会被重新定义。
开发者需要区分三类风险
这类机制落地后,开发者面对的风险并不完全相同。
一类是安装失败风险。用户下载 APK 后,系统可能在安装前给出更强警告,甚至直接阻止安装。对依赖官网 APK、GitHub Release、F-Droid、企业私有仓库的项目来说,这会直接影响转化和支持成本。
第二类是身份绑定风险。如果验证器要求开发者身份进入某种中心化登记流程,个人开发者、匿名贡献者、社区维护者会遇到额外门槛。安全团队喜欢“可追责”,但开源社区还依赖低摩擦贡献和分叉发布。
第三类是生态依赖风险。只要一个远程策略系统能改变安装行为,发行渠道就必须考虑“今天能装,明天是否还能装”。这不一定意味着 Google 一定会滥用它,但工程上要把这种外部开关当作供应链风险来管理。
可以这样实践:检查测试机上的安装与验证状态
下面的命令不是对 ADV 内部行为的完整检测,也不能证明设备是否已经被远程激活。它的作用更朴素:帮助 Android 开发者在测试机上记录安装来源、包验证相关设置,以及 sideload 流程是否发生变化。运行前需要安装 Android Platform Tools,并打开设备 USB 调试。
#!/usr/bin/env bash
set -euo pipefail
adb devices
echo "\n== Device version =="
adb shell getprop ro.build.version.release
adb shell getprop ro.build.version.sdk
echo "\n== Package verifier related settings =="
adb shell settings get global package_verifier_enable || true
adb shell settings get global verifier_verify_adb_installs || true
adb shell settings get global package_verifier_user_consent || true
echo "\n== Known verifier / package installer packages =="
adb shell pm list packages | grep -Ei 'verifier|packageinstaller|permission|gms|vending' || true
echo "\n== Install source support check =="
adb shell cmd package get-install-location || true
保存为 android-install-audit.sh 后执行:
chmod +x android-install-audit.sh
./android-install-audit.sh
如果你维护一个不通过 Google Play 分发的 APK,可以在 CI 或发布前增加一台真实设备做安装冒烟测试。下面是一个最小例子,假设你已经构建出 app-release.apk:
#!/usr/bin/env bash
set -euo pipefail
APK_PATH="${1:-app-release.apk}"
PACKAGE_NAME="${2:-org.example.app}"
adb install -r "$APK_PATH"
adb shell monkey -p "$PACKAGE_NAME" -c android.intent.category.LAUNCHER 1
adb shell pm path "$PACKAGE_NAME"
运行时替换成你的 APK 路径和包名:
./smoke-install.sh ./app/build/outputs/apk/release/app-release.apk org.fdroid.fdroid
这个脚本不会绕过系统策略。它的价值在于让团队尽早发现:安装提示是否变化、ADB 安装是否被验证器拦截、包是否能正常启动。对面向普通用户的 sideload 分发,还应补充手工测试,因为用户从浏览器、文件管理器、第三方商店安装时触发的路径可能不同。
对第三方应用商店,技术对策要更具体
F-Droid 的激烈表态背后,是第三方应用商店长期面对的结构性问题:平台安全策略常常以“保护用户”为名收紧,但真正受影响的是替代分发渠道。
开发者可以做几件务实的事。
公开构建与签名信息。用户和下游仓库需要知道 APK 从哪里来、由谁签名、对应哪个源码提交。至少提供 SHA-256、签名证书指纹、版本号和源码标签。
保留多条分发路径。不要只依赖单一商店。官网、F-Droid、GitHub Release、企业仓库可以并存,但要避免让用户在多个渠道之间交叉升级造成签名不一致。
记录安装失败证据。当用户报告“无法安装”时,引导他们提供 Android 版本、安装来源、错误截图和 adb logcat 片段。没有这些信息,团队很难判断是签名问题、SDK 限制、包冲突,还是系统验证策略变化。
下面是一个可以放进发布流程的校验片段,用于生成 APK 摘要,便于发布说明复用:
APK="app-release.apk"
sha256sum "$APK"
apksigner verify --print-certs "$APK"
需要安装 Android SDK Build Tools,并把 apksigner 加入 PATH。发布时把 SHA-256 和证书指纹写清楚,比一句“请信任我们”更有用。
采用建议:把 ADV 当作分发供应链风险处理
F-Droid 把 ADV 称为恶意软件,这个判断带有明确立场。工程团队不必照搬措辞,但应该认真处理它指出的风险:安装验证机制一旦由平台方远程控制,应用分发就多了一个不可忽视的外部依赖。
可以用这份清单做一次内部评估:
- 你的 Android 应用是否依赖 Google Play 之外的安装路径?
- 是否记录每个版本的 APK 哈希、签名证书和源码提交?
- 是否在 Android 8 及以上的真实设备上测试 sideload?
- 用户安装失败时,客服或 issue 模板是否能收集到足够诊断信息?
- 如果某个渠道突然被系统警告或阻断,是否还有可解释、可验证的备用渠道?
安全和开放分发之间一直有张力。真正的问题不是要不要验证应用,而是验证规则是否透明、是否可申诉、是否尊重用户对设备的控制权。对开发者来说,最稳妥的姿势是把分发链路做得可审计、可复现、可替换。这样即使平台策略变化,也不会在发布当天才发现自己的用户被挡在安装按钮之外。