Captive Portal 检测机制工作原理详解
触发时机
检测在这些场景会自动跑一遍:
- WiFi 连上一个新网络时
- WiFi 从断开切到连接时
- 移动数据开关从关切到开时
- 飞行模式关闭后恢复连接时
另外,系统会每隔一段时间周期性地重新检测,所以改完参数如果不手动刷新,过一会儿它自己也会再来一次。
标准判定流程
系统后台发起请求
↓
HTTP 探测地址返回了 204?
├─ 是 → 图标干净,检测结束
└─ 否 → 继续 HTTPS 探测(Android N 起)
↓
HTTPS 探测地址返回 204?
├─ 是 → 图标干净(可能提示有强制门户)
└─ 否 → 挂感叹号或叉
HTTPS 探测是安卓 7 新增的,目的是防止 HTTP 探测被强制门户的登录页(通常是 HTTPS)干扰。所以从 Android N 起,系统会同时发两个探测:一个 HTTP、一个 HTTPS。
为什么非要返回 204
HTTP 204 这个状态码的含义是「服务器成功处理了请求,但不需要返回任何实体内容」。选它的原因是:
- 强制门户登录页几乎不会返回 204(登录页是 HTML,通常是 200 或 302)
- 正常的网关/验证服务器可以很轻量地返回 204,不需要建个完整的网页
- 用户自己发请求看到的是个空响应,也不影响什么
大陆环境的问题
原生系统默认探测地址指向 Google 的服务器(如 connectivitycheck.gstatic.com/generate_204)。在中国大陆,这类域名直连不稳定,甚至直接被阻断。结果就是:
- 请求超时 → 系统判定「无网络」
- 图标挂 × 或 !
- 但用户的应用走的是代理或其他正常通道,实际上能上网
这就是「明明能刷视频,图标却挂感叹号」的根本原因。CaptiveMgr 做的就是把这两个探测 URL 换到国内可达的服务器上。
settings global 参数
安卓通过 settings global 这组系统参数来存储探测配置。涉及的参数随版本不同有差异,详见「安卓版本参数变化」。CaptiveMgr 本质上就是给这几个参数写值。