自己在本地环境里被Connect timed out坑过多少次,估计很多 Android 开发者都数不清了。我最近把积压已久的老项目重新拉回电脑,Android Studio 版本刚升完,打开工程等着 Gradle Sync,进度条在某个依赖上停了两分钟后,构建窗口抛出一串Connect timed out。那一刻我的第一反应是“断网了”,但手机Wi-Fi明明满格。后来反复排查才意识到,这句话就像一张没有写清楚收件地址的快递单:Gradle 同步、ADB 连接、模拟器调试、SDK 下载,每一个环节都可能吐出一句 Connect timed out,每次背后的原因和修法完全不同。
这篇文章把我在实际项目中遇到过的各种“Connect timed out”场景串起来讲一遍。你会看到我真正用过的排查命令、改过的配置文件和踩过的坑,按顺序走一遍,大部分问题都能定位到根上。
1. 先分清这个Connect timed out是从哪一层冒出来的
不管报错文案多吓人,动手改配置之前一定要先做一件事:确定这个超时发生在哪一层。Android Studio 是个“多进程 + 多网络链路”的大家伙,Gradle 进程、ADB 服务、模拟器进程、SDK 下载组件各自有独立的网络通道,每个通道超时的原因、排查范围、修复手段完全不同。如果在还没定位的情况下盲目改镜像配置,往往白忙一下午。
1.1 看Build窗口还是Logcat窗口
最简单的方法就是看报错出现在哪个窗口。Build窗口里出现Connect timed out,大概率是 Gradle 在解析或下载依赖时网络受阻。Logcat窗口里出现连接超时,或者Run窗口在启动阶段卡住,则多半是 ADB、调试器、模拟器链路的问题。
我把平时常遇到的报错场景整理成了对照表,排查时直接对号入座:
| 报错出现的环节 | 典型文案 | 大概率原因 | 优先检查项 |
|---|---|---|---|
| Gradle Sync | Could not resolve all files / Connect timed out | 依赖仓库不可达 | 镜像仓库、DNS、Gradle 配置 |
| Gradle Build | Artifact download timed out | 依赖下载超时 | 网络环境、本地缓存 |
| Run / 调试器 | Unable to open debugger port | 端口冲突、ADB 链路异常 | 5037端口、adb devices |
| Logcat 启动 | Failed to connect to localhost | 模拟器访问宿主机地址错误 | 10.0.2.2、adb reverse |
| SDK Manager | Download interrupted / timed out | SDK 下载地址不可达 | dl.google.com 连通性 |
| Plugins 市场 | Could not connect to plugins server | 插件市场 CDN 响应慢 | 官网手动下载插件 |
这张表虽简单,但能省掉大量重复排查。别人找我处理类似问题时,我第一句永远问:报错是在哪个窗口、哪一步操作之后出现的?这不是客套话,报错位置基本决定了排查方向。
1.2 看日志里真正连的那个地址
第二步是找到日志中包含的 URL。Gradle 同步超时时,错误信息里大概率会残留完整地址。最常见的几个地址是dl.google.com、repo.maven.apache.org,以及公司内网仓库地址。不同地址对应的策略完全不同:
- 超时地址是
dl.google.com或maven.google.com:负责 Android Gradle Plugin 和 Google 系依赖的分发。国内环境下直连经常不稳定,优先考虑切换仓库镜像。 - 超时地址是
repo.maven.apache.org:Maven Central 的连接问题,同样用镜像解决。 - 超时地址是公司内部的 Nexus 仓库:先问运维仓库服务是否在线,再查本机 hosts 和防火墙。
- 超时地址是
services.gradle.org:Gradle Wrapper 正在下载发行包,和依赖仓库无关,属于另一类问题。
把上面这个地址复制到浏览器直接访问一遍,如果浏览器都打不开,说明问题根本不在 Android Studio,而在系统网络层面。这时回去折腾 IDE 设置就是浪费时间。
2. Gradle依赖同步超时:一套完整的排查与修复流程
如果确认是 Gradle 依赖下载超时,那就可以按下面这套流程处理。这套流程是我在多个项目上验证过的,按顺序执行能覆盖绝大多数情况。
2.1 先验证本机到仓库的网络连通性
打开终端,用 curl 测一下仓库的响应状态。以国内最常用的阿里云镜像为例:
curl -I -m 10 https://maven.aliyun.com/repository/google如果返回HTTP/1.1 200 OK,说明本机到镜像站的链路是通的,问题大概率出在 Gradle 配置或 DNS 缓存。如果是Connection timed out,说明确实到了网络层,需要继续查 DNS。
接着执行:
nslookup maven.aliyun.com ping maven.aliyun.com如果域名解析出来但 ping 不通,或者解析结果非常诡异,就要检查系统的 hosts 文件。Windows 上在C:\Windows\System32\drivers\etc\hosts,macOS 和 Linux 在/etc/hosts。我曾在同事电脑上发现过安全软件往 hosts 里塞了一行dl.google.com的内网沙箱地址,结果 Android Studio 同步什么依赖都超时,排查了很久才发现是这行残留记录在捣乱。
2.2 把Maven仓库切换成镜像仓库
确认网络没问题后,最直接的操作就是改仓库配置。新版 Android Studio 项目默认把仓库配置写在settings.gradle的dependencyResolutionManagement里,我建议改成下面的样子:
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } google() mavenCentral() } }这里把镜像仓库放在google()和mavenCentral()前面,Gradle 解析依赖时会优先从镜像拉取。镜像服务本质上是在本地或国内节点缓存了上游仓库的构件,响应速度和稳定性都会好很多。
要注意两个细节:
FAIL_ON_PROJECT_REPOS会禁止子模块再单独声明仓库,避免各个模块的仓库列表不一致导致解析混乱。- 部分冷门第三方 SDK 只发布在已停止维护的 JCenter 路径上,镜像也不一定覆盖。这类构件只能用公共镜像兜底,或者干脆把 jar/aar 下载到本地用
implementation files()引入。
2.3 调大Gradle的HTTP超时时间
加了镜像之后还有少数场景会超时,尤其是体积较大的依赖下载。Gradle 默认的 HTTP 连接超时只有 30 秒左右,在高峰期从远程拉一个几十 MB 的包很容易触发。此时可以修改gradle.properties:
org.gradle.internal.http.connectionTimeout=180000 org.gradle.internal.http.socketTimeout=180000单位是毫秒,connectionTimeout是建立 TCP 连接的超时时间,socketTimeout是建立连接后等待数据的超时时间。我一般直接配置成 180000,也就是 3 分钟,既不会让一次失败卡太久,也足够应对正常的大包下载。
2.4 确认是不是Gradle Wrapper本身在下载
还有一种容易忽略的超时,发生在 Gradle 同步最开始的阶段,报错信息里带有gradle-8.x-bin.zip之类的字样。这是因为项目里的gradle/wrapper/gradle-wrapper.properties指向了services.gradle.org,而 Gradle 需要先下载对应发行版才能执行构建。
我的处理办法有两种:
- 手动下载对应版本的 Gradle 压缩包,放到本地目录,然后修改
gradle-wrapper.properties:
distributionUrl=file\:/D:/tools/gradle-8.7-bin.zip- 在 Android Studio 的 Settings -> Build Tools -> Gradle 里选择 Local distribution,直接指定本地已解压的 Gradle 目录。
这个方法尤其适合经常新建项目的场景。新建项目时 Android Studio 经常会拉一个你本地没有的 Wrapper 版本,跑一次全量下载很容易碰上超时,换成本地版本能彻底绕开。
2.5 依赖缓存和离线模式兜底
如果项目之前已经成功同步过一次,那么所有依赖其实都缓存在本地的~/.gradle/caches目录里。此时可以直接打开 Android Studio 的离线模式:File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle,勾选 Offline work。
离线模式会跳过所有远程仓库检查,直接使用本地缓存,构建速度快得多。我的习惯是:只有在新增依赖或切换分支时才切回在线模式拉取一次,其余时间保持离线。注意,离线模式下如果在缓存中找不到某个构件,构建会立刻报“找不到依赖”,这时候不用慌,切回在线模式同步一次就行。
3. 模拟器里连不上本机调试服务:一个很容易踩的坑
另一种极其常见的场景是:项目已经跑起来了,App 成功安装到模拟器,但应用里请求本地后端接口时一直Connect timed out。很多人把这个问题归咎于电脑网络,其实问题恰恰出在“localhost 的理解方式不同”。
3.1 模拟器里的localhost不是你宿主机
Android 模拟器内部是一个虚拟的 NAT 网络环境,它在自己内部维护了一个独立的环回地址。你在模拟器里访问localhost,访问到的是模拟器自己,而不是开发电脑。宿主机在模拟器网络栈里有专门的映射地址,也就是10.0.2.2。
所以代码里的 BaseUrl 如果写成http://localhost:8080,在模拟器里必然连不上,表现就是连接超时或连接拒绝。正确写法是:
"http://10.0.2.2:8080"另外提醒一句,如果后端跑的是 HTTP 明文接口,Android 9 及以上系统默认禁止明文流量。这时候还需要在res/xml/network_security_config.xml里做允许配置,否则你可能会看到另一个“连接失败”的错误,很容易和超时混在一起。
3.2 用adb reverse把端口映射到模拟器
如果你不想为了调试环境去改 BaseUrl,更优雅的办法是使用adb reverse。这个命令可以把模拟器里的端口反向映射到宿主机:
adb reverse tcp:8080 tcp:8080执行之后,模拟器里访问http://localhost:8080,请求会通过 ADB 转发到宿主机的 8080 端口。这个方案对真机调试同样适用,而且不要求手机和电脑在同一网段。唯一要注意的是,设备重连或 ADB 服务重启后映射会失效,需要重新执行,定期使用建议写进启动脚本里。
3.3 真机Wi-Fi调试时容易被忽略的网络限制
真机无线调试的场景里,最常见的超时原因是手机和电脑不在同一个局域网。Android 11 及以上可以用系统的无线调试配对功能,Android Studio 会通过 mDNS 发现设备。如果发现设备后连接一直卡在timed out,先检查路由器是否开启了 AP 隔离。很多办公路由默认开启这个功能,它会让同一 Wi-Fi 下的设备互相不能访问。其次是检查手机和电脑是否落在同一网段,跨网段时该路由就不可达。这两点确认之后,无线调试基本都能稳定连上。
4. ADB连接层的超时:从重启发到端口占用
还有一种情况是点了 Run 按钮,Android Studio 一直卡在Connect timed out: adb,或者弹Unable to open debugger port。这类问题属于 ADB 链路故障,我按下面的顺序逐一排查。
4.1 先看adb devices的输出
在终端执行:
adb devices正常输出会显示一串设备列表,设备名右侧的状态是device。如果状态是offline,说明链路已经异常;如果是unauthorized,说明手机上的 USB 调试授权弹窗还没确认;如果列表为空,则属于 ADB 服务没识别到设备。
一个容易被忽略的点是:Android Studio 的设备列表里能看到设备,并不代表 ADB 链路正常。很多时候设备虽然出现在列表里,但状态是 offline,点 Run 照样超时。所以每次先以命令行的adb devices状态为准。
4.2 重启ADB并处理端口占用
最常见的修复动作是重置 ADB 服务:
adb kill-server adb start-server adb devices如果执行后卡在* daemon not running. starting it now on port 5037并一直无响应,说明 5037 端口被占用。Windows 上可以查看:
netstat -ano | findstr 5037macOS 和 Linux 上可以用:
lsof -i :5037找到占用端口的进程号后,去任务管理器或进程管理工具确认是不是其他硬件调试工具占用了这个端口。我之前遇到过一个串口调试软件把 5037 占了,Android Studio 怎么连都报超时,关掉那个软件后重置 ADB 马上恢复。
4.3 防火墙和安全软件对ADB的拦截
这个原因不太显眼,但发生概率不低。部分安全软件会拦截 ADB 回连设备时使用的临时端口,现象是手机端已经显示 USB 调试已连接,授权弹窗也点了允许,但 ADB 依旧超时。这时候试着把 Android Studio 和 adb 进程加入防火墙白名单,或者临时关闭安全软件再做一次adb kill-server && adb start-server,大概率立刻恢复。这类问题即使重装 Android Studio 也依然存在,因为拦截发生在系统层。
5. SDK下载与插件市场超时:Android Studio自身的网络问题
除了项目构建链路,Android Studio 本身也有联网需求。SDK Manager 下载组件时偶尔会超时,插件市场加载列表时也经常转圈半天然后报错。这类问题不能通过项目配置解决,得从 Android Studio 的角度去处理。
5.1 SDK组件的下载地址与DNS刷新
Android Studio 的 SDK 组件默认从dl.google.com拉取。如果你所在的网络环境对这条链路不稳定,下载进度条就会卡住。首选动作是刷新 DNS 缓存,排除域名解析脏数据的影响。Windows 上执行:
ipconfig /flushdnsmacOS 上执行:
sudo dscacheutil -flushcache如果刷新后仍超时,可以把需要下载的 SDK 组件拿到另一台网络环境正常的机器上,先下载好 Platform 和 Build-Tools 完整目录,再拷贝到本机的~/Library/Android/sdk(macOS)或C:\Users\你的用户名\AppData\Local\Android\Sdk(Windows)下。Android Studio 启动时会自动识别这些组件,完全不需要走下载流程。
5.2 插件市场超时的另类安装方式
Plugins 页面加载不出列表,甚至报Connect timed out,很多时候是插件市场的 CDN 响应慢。插件市场本身没有太多可配置项,我推荐绕开它:直接到 JetBrains 官网搜索需要的插件,下载 zip 包,然后在 Settings -> Plugins 里选择 Install Plugin from Disk。这个方式不受市场页面连接状态影响,我一直在用,稳定且省时间。
6. 最后一次整理:一组能有效防复发的配置和习惯
前面讲了那么多排查手段,最后说说怎么让这个问题少发生。依赖下载超时这种事,修好一次容易,难的是不要在下个网络环境里再次爆发。
6.1 gradle.properties里的合理默认值
把下面这些配置放进gradle.properties,基本能保证大多数项目的同步过程更稳:
org.gradle.daemon=true org.gradle.parallel=true org.gradle.caching=true org.gradle.internal.http.connectionTimeout=180000 org.gradle.internal.http.socketTimeout=180000 org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m需要留意的是,超大项目的多模块并行构建对内存依赖较高。如果配置了并行构建之后构建反而变慢甚至卡死,把org.gradle.parallel改回false再试,别一味追求并行。
6.2 团队共享一份依赖缓存
依赖拉取问题最烦人的地方在于:一个人修好了,换台机器照样踩。如果开发团队的网络环境普遍一般,可以考虑在局域网内共享 Gradle 缓存。将其中一台网络较好的机器作为“编译机”,先在编译机上完成一次全量依赖同步,然后通过共享目录让其他成员复用~/.gradle/caches。这种方法比每个人各自下载省事得多,新加入的成员首次构建也能很快完成。
6.3 离线构建作为最终兜底
最后想分享一个我坚持了很久的习惯:在项目依赖锁定之后,专门用一次离线模式跑完整构建,确认所有构件都已经落进缓存。这样即使后续网络彻底抽风,至少还能保持一个可用的构建环境。之前出差途中遇到酒店网络半瘫痪,我就是靠离线构建完成了当天所有任务的交付,关键时刻真的能救命。