Android 10及以上版本出现SocketTimeoutException等网络崩溃问题
Android 10+ 网络崩溃问题排查与解决方案需求
核心崩溃异常
在Android 10及以上版本,应用出现崩溃,核心异常为:
(Platform.kt 第128行 okhttp3.internal.platform.Platform.connectSocket)
Fatal Exception: java.net.SocketTimeoutException 120000ms后仍无法从/某IP(端口37062)连接到domain/IP(端口443):isConnected失败: ETIMEDOUT(连接超时)
Firebase Crashlytics崩溃堆栈详情
libcore.io.IoBridge.isConnected (IoBridge.java:343) java.net.Socket.connect (Socket.java:646) okhttp3.internal.platform.Platform.connectSocket (Platform.kt:128) okhttp3.internal.connection.ConnectPlan.connectSocket (ConnectPlan.kt:246) okhttp3.internal.connection.ConnectPlan.connectTcp (ConnectPlan.kt:128) okhttp3.internal.connection.SequentialExchangeFinder.find (SequentialExchangeFinder.kt:41) okhttp3.internal.connection.RealCall.initExchange$okhttp (RealCall.kt:267) okhttp3.internal.connection.ConnectInterceptor.intercept (ConnectInterceptor.kt:32) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.cache.CacheInterceptor.intercept (CacheInterceptor.kt:96) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.http.BridgeInterceptor.intercept (BridgeInterceptor.kt:83) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept (RetryAndFollowUpInterceptor.kt:75) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) co.bosta.bosta_star_app.di.NetworkModuleKt$networkModule$1$invoke$provideOkHttpClient$$inlined$-addInterceptor$1.intercept (OkHttpClient.kt:1156) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.logging.HttpLoggingInterceptor.intercept (HttpLoggingInterceptor.kt:155) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp (RealCall.kt:205) okhttp3.internal.connection.RealCall$AsyncCall.run (RealCall.kt:533) java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1137) java.lang.Thread.run (Thread.java:1012) Caused by android.system.ErrnoException isConnected failed: ETIMEDOUT (Connection timed out) libcore.io.IoBridge.isConnected (IoBridge.java:334) java.net.Socket.connect (Socket.java:646) **okhttp3.internal.platform.Platform.connectSocket (Platform.kt:128)** okhttp3.internal.connection.ConnectPlan.connectSocket (ConnectPlan.kt:246) okhttp3.internal.connection.ConnectPlan.connectTcp (ConnectPlan.kt:128) okhttp3.internal.connection.SequentialExchangeFinder.find (SequentialExchangeFinder.kt:41) okhttp3.internal.connection.RealCall.initExchange$okhttp (RealCall.kt:267) okhttp3.internal.connection.ConnectInterceptor.intercept (ConnectInterceptor.kt:32) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.cache.CacheInterceptor.intercept (CacheInterceptor.kt:96) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.http.BridgeInterceptor.intercept (BridgeInterceptor.kt:83) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept (RetryAndFollowUpInterceptor.kt:75) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) co.bosta.bosta_star_app.di.NetworkModuleKt$networkModule$1$invoke$provideOkHttpClient$$inlined$-addInterceptor$1.intercept (OkHttpClient.kt:1156) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.logging.HttpLoggingInterceptor.intercept (HttpLoggingInterceptor.kt:155) okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:109) okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp (RealCall.kt:205) okhttp3.internal.connection.RealCall$AsyncCall.run (RealCall.kt:533) java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1137) java.lang.Thread.run (Thread.java:1012)
关联网络崩溃问题
- Dns.kt 第49行 okhttp3.Dns$Companion$DnsSystem.lookup:
java.net.UnknownHostException无法解析主机"host.com":无关联主机地址 - Http2Stream.kt 第675行 okhttp3.internal.http2.Http2Stream$StreamTimeout.newTimeoutException:
java.net.SocketTimeoutException超时 - ConnectPlan.kt 第315行:
javax.net.ssl.SSLHandshakeExceptionSSL握手中止: ssl=0x75dd3e3848: 系统调用期间I/O错误,软件导致连接中止;JvmOkio.kt 第94行 okio.InputStreamSource.read:java.net.SocketException软件导致连接中止
已尝试的超时配置
已添加以下OkHttp超时设置,但崩溃未解决:
.connectTimeout(120, TimeUnit.SECONDS) .readTimeout(120, TimeUnit.SECONDS) .writeTimeout(120, TimeUnit.SECONDS)
网络连接检测代码
发起API请求前,使用以下方法检测网络连接:
fun isConnected(): Boolean { val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val networkInfo=connectivityManager.activeNetworkInfo val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) if (capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) { when { capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> { return true } capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> { return true } capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> { return true } } } } else { val activeNetworkInfo = connectivityManager.activeNetworkInfo if (activeNetworkInfo != null && activeNetworkInfo.isConnected) { return true } } return false }
解决方案建议
1. 优化OkHttp重试与超时策略
当前120秒的超时过长,反而会增加用户等待时间和崩溃概率。建议调整为更合理的数值(如15-30秒),同时启用OkHttp的重试机制,并添加调用超时限制整个请求的总时长:
.connectTimeout(20, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .writeTimeout(20, TimeUnit.SECONDS) .callTimeout(60, TimeUnit.SECONDS) .retryOnConnectionFailure(true)
2. 处理DNS解析异常
配置OkHttp使用自定义DNS服务器,避免系统DNS解析失败,同时增加DNS缓存减少重复解析:
.dns(Dns { hostname -> try { InetAddress.getAllByName(hostname).toList() } catch (e: UnknownHostException) { // fallback到公共DNS InetAddress.getAllByName("8.8.8.8").toList() } })
3. 修复网络检测的局限性
当前检测仅能确认网络可达,无法保证能连接到目标服务器。建议在检测后添加轻量级健康检查请求,确认实际连通性:
suspend fun isServerReachable(): Boolean { return try { val client = OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) .build() val request = Request.Builder().url("https://your-server.com/health").head().build() client.newCall(request).execute().isSuccessful } catch (e: Exception) { false } }
注意在协程中执行此操作,避免阻塞主线程。
4. 处理SSL握手异常
- 确认服务器SSL证书有效,支持Android 10+的TLS 1.2及以上版本;
- 配置OkHttp兼容主流TLS版本:
.connectionSpecs(listOf(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
5. 全局异常捕获避免崩溃
在OkHttp拦截器中统一捕获网络异常,返回友好响应而非直接崩溃:
addInterceptor { chain -> try { chain.proceed(chain.request()) } catch (e: IOException) { Response.Builder() .request(chain.request()) .protocol(Protocol.HTTP_1_1) .code(503) .message("网络异常") .body(ResponseBody.create(null, "")) .build() } }
内容的提问来源于stack exchange,提问作者Amin
相关产品推荐
相关产品推荐

