Android 模拟器代理联网与 No Internet WiFi 锁死排查 - 开发环境与网络避坑 04
问题概览卡片
基本信息
- 问题分类:模拟器网络联通 / 代理配置冲突 / 开发服务接入调试
- 环境说明:macOS (M系列) / Android SDK Emulator / Clash Verge / Android 14+
- 触发条件:在未开全局 Tun 模式下,多处重叠配置代理,或由于国内网络环境下模拟器对 Google 检测服务不通引发的自动降级。
- 报错表现:
并且模拟器 WiFi 标志上出现小感叹号,提示 “No internet”。
1
2
3 This site can't be reached
www.google.com took too long to respond.
ERR_TIMED_OUT
1. 现象描述与现场还原
在日常开发或接入需要连接 Google 服务的 App 时,我们需要在模拟器上连接 Google 服务以测试各项网络接口或登录商店。
当我们尝试将模拟器的流量导入宿主机(Mac)运行的代理客户端(如 Clash 端口 7890)时,经常会遇到以下现象:
- 模拟器内开浏览器访问谷歌,提示
ERR_TIMED_OUT。 - 模拟器 WiFi (AndroidWifi) 状态一直显示为 “Connected, no internet” (已连接,无互联网),并且带有一个感叹号。
- 最诡异的是:如果关闭 WiFi 改用蜂窝流量 (Mobile Data),能正常访问百度、必应等国内网站;但只要连着配置了代理的 WiFi,连百度也一并报
ERR_TIMED_OUT,网络完全瘫痪。
2. 根本原因分析
该问题背后有三个互相层叠的隐藏网络机制:
2.1 模拟器网络沙箱与 10.0.2.2 宿主映射
Android 模拟器运行在独占的虚拟机沙箱中,它的网络是一个虚拟的局域网网段。
- 在模拟器内部,
10.0.2.2是指向宿主机 Mac 环回接口(Loopback /127.0.0.1)的特殊网关。 - 局域网入站拦截:如果您的 Clash 客户端未开启 “允许局域网 (Allow LAN)”,Clash 核心将只监听
127.0.0.1,任何来自虚拟网桥(来自10.0.2.16等模拟器 IP 发往10.0.2.2)的连接都会被 Clash 视作 LAN 入站流量并直接拒绝接收。
2.2 Captive Portal 锁死路由 (No Internet 机制)
当 Android 连上 WiFi 后,会向 Google 专属服务器发送一个轻量 HTTP 请求(connectivitycheck.gstatic.com)以确定是否需要弹窗输入网页认证。
- 如果在代理生效前,该检测请求被墙或超时,Android 会认定此 WiFi “没有互联网连接”。
- 网络降级逻辑:为了保证手机能正常通网,Android 系统在判定 WiFi 无网时,会自动忽略此 WiFi 的路由出口,强行把全局流量降级退回到不含代理配置的蜂窝移动网络(Cellular Data)。
- 这就导致了“连着 WiFi 无网,断开 WiFi 能用蜂窝网络上国内网,但代理和谷歌永远不通”的恶性循环。
2.3 命令行 -http-proxy 与 WiFi 手动代理的双重冲突
有些开发者为了省事,使用如下命令行参数启动模拟器:
1 | emulator -avd Pixel_9_Pro -http-proxy http://127.0.0.1:7890 |
启动后,又去模拟器的系统设置(WiFi Advanced Settings)里手动设置了 10.0.2.2:7890 的 Manual Proxy。
- 此时,命令行参数在模拟器底层进程(QEMU 级别)劫持流量;而系统 WiFi 设置在 Android 系统级别又强行做了一层代理包装。
- 这种代理叠加导致了 Proxy Chaining 环路冲突,两层代理相互等待,导致所有 HTTP 请求死锁,直接报
ERR_TIMED_OUT。
3. 解决方案与最佳实践
3.1 一键消除 No Internet:关闭系统 Captive Portal 检测
在 Mac 宿主机上,我们直接使用 Android SDK 附带的 adb 工具对运行中的模拟器下发全局配置,彻底关掉 Google 连网检测,使 WiFi 永久保持在“有网”的健康路由状态。
请在终端中执行以下命令(模拟器需保持运行状态):
1 | # 1. 彻底禁用 Captive Portal 网络检测模式 |
执行后,模拟器的 WiFi 图标感叹号会瞬间消失,路由状态恢复正常。
3.2 代理联网配置方案(三选一)
在关闭检测后,建议选择以下其中一种方式干净地配置代理,切勿重叠使用:
方案 A:宿主开启局域网共享 + 模拟器 WiFi 手动代理(最常用)
- 宿主配置:在 Mac 的 Clash 菜单中,勾选 “允许局域网连接” (Allow LAN) 开关。
- 模拟器配置:
- 启动模拟器时不要带
-http-proxy参数。 - 进入模拟器 WiFi (AndroidWifi) -> 铅笔编辑 -> 展开高级选项 -> Proxy 选择 Manual。
- Host name 填入宿主网关:
10.0.2.2。 - Port 填入 Clash 的 HTTP 端口:
7890。 - 保存。
- 启动模拟器时不要带
方案 B:宿主开启 Tun 模式 + 模拟器无代理参数(最省心 )
- 安装核心服务:在 Mac 的 Clash 中点击“更多设置” -> 找到 “服务模式” (Service Mode) 点击安装并授权(授权后其状态图标会变为绿色)。
- 开启 Tun:在 Clash 主菜单中勾选开启 “Tun 模式”(此时 Mac 会建立一块接管整机流量的虚拟网卡)。
- 模拟器配置:
- 将模拟器内所有的 WiFi 代理修改为 None (无)。
- 直接运行最普通的模拟器启动命令,即可完美接入代理网络,无需配置任何代理参数。
方案 C:仅使用命令行参数代理(免改系统设置)
- 模拟器配置:将模拟器内的 WiFi 代理重置为 None (无)。
- 启动命令:若 HTTP 代理不通,推荐采用兼容性更佳的 SOCKS5 协议从命令行启动:(注:7891 为 Clash 的默认 SOCKS5 端口)
1
~/Library/Android/sdk/emulator/emulator -avd Pixel_9_Pro -http-proxy socks5://127.0.0.1:7891 &
4. 补充说明:Google Play 商店镜像注意事项
在解决网络问题后,若要测试真正的 Google Play 商店或相关谷歌服务,还需要确保您的 Android 模拟器不是 google_apis 镜像。
- 如何判断:启动模拟器时的命令行日志如果输出如下内容,则说明是
google_apis镜像:Found systemPath .../google_apis/arm64-v8a/ - 正确做法:在 Android Studio 的 Device Manager 中创建虚拟设备时,必须选择带“三角 Play 商店图标”的物理机型,并下载 Target 标明为
Android ... (Google Play)的系统镜像(此时镜像存储路径应为.../google_play/arm64-v8a/)。 - 登录 Google Play 商店后,配合上述代理机制,即可在本地开发环境中轻松访问商店并下载调试应用。
5. 关于配置持久性与 Wipe Data 的说明
很多开发者会担心这些配置是否每次启动模拟器或重启电脑后都需要重新设置。答案是:不需要,这些设置是持久生效的。
- ADB 修改全局设置:我们执行的
captive_portal禁用命令写入的是 Android 虚拟机的系统全局数据库(保存在/data分区内)。模拟器重启或关机并不会丢失这一配置。 - WiFi 代理配置:系统内置的 WiFi 代理设置也会被保存在模拟器的本地网络配置中,同样永久生效。
- Clash 局域网设置:宿主机的 Clash “允许局域网连接”设置属于本地应用配置,软件重启依然保持开启。
例外情况:
唯一会导致上述配置失效的操作是,在 Android Studio Device Manager 中对该模拟器执行了 “Wipe Data” (擦除数据/恢复出厂设置)。擦除数据会清空整个/data分区,届时您需要重新下发一次 ADB 连网检测禁用命令并重置 WiFi 手动代理。