问题描述
问题:一旦返回 UnkNownHostException,用户将继续收到相同的错误,除非重新安装应用程序或重新启动设备。
在操作系统为 Android 11 的用户中,只有少数用户遇到问题。
最大的问题是,当出现错误时,每次请求都会不断返回相同的错误。
据用户称,重新安装应用程序或重新启动设备会再次工作。
似乎 99% 是三星设备的用户。有时还有 Google Pixel 手机。
Http 和 Https 都给出相同的错误。
Wifi、5G 和 LTE 都会出现相同的错误。
请求方法是使用POST,不知道GET是否也是这样,我没有使用GET。
这是我的代码
Gradle:
android {
minSdkVersion 21
kotlinoptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
/* RETROFIT */
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
/* OKHTTP */
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.0'
/* RXJAVA RXANDROID */
implementation 'io.reactivex.rxjava3:rxjava:3.0.11'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
}
创建请求:
interface ApiService {
@POST("get-data")
fun getData(@Body parameter : CustomParameter): Single<Response<CustomObject>>
companion object {
private val rxJava3CallAdapterFactory: RxJava3CallAdapterFactory
get() = RxJava3CallAdapterFactory.createWithScheduler(Schedulers.io())
private fun okHttpClient(): OkHttpClient {
val okHttpClientBuilder = okHttpClientBuilder()
okHttpClientBuilder.addNetworkInterceptor { chain ->
val request = chain.request()
val response = chain.proceed(request)
if (response.code >= 400) {
handleNetworkError()
}
response
}
okHttpClientBuilder.addInterceptor { chain ->
val request = chain.request()
chain.proceed(request)
}
return okHttpClientBuilder.build()
}
fun createApiService(context: Context): ApiService {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(rxJava3CallAdapterFactory)
.client(okHttpClient())
.build()
return retrofit.create(ApiService::class.java)
}
}
}
呼叫请求(活动中):
ApiService.createMainWeatherApiService().getData(CustomParameter())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ res ->
handleSuccess()
},{ error ->
// UnkNownHostException!!!!
handleFail()
}
).apply { compositedisposable.add(this) }
我在 okhttp 上创建了一个问题:https://github.com/square/okhttp/issues/6591
解决方法
您能否包含事件侦听器的输出,该输出将显示 OkHttp(通常)使用系统 DNS 提供程序进行的 DNS 调用?
https://stackoverflow.com/a/66398516/1542667
[0 ms] callStart: Request{method=GET,url=https://httpbin.org/get}
[11 ms] proxySelectStart: https://httpbin.org/
[12 ms] proxySelectEnd: [DIRECT]
[12 ms] dnsStart: httpbin.org
[55 ms] dnsEnd: [httpbin.org/54.147.165.197,httpbin.org/34.231.30.52,httpbin.org/54.91.118.50,httpbin.org/18.214.80.1,httpbin.org/54.166.163.67,httpbin.org/34.199.75.4]
[62 ms] connectStart: httpbin.org/54.147.165.197:443 DIRECT
[176 ms] secureConnectStart
[747 ms] secureConnectEnd: Handshake{tlsVersion=TLS_1_2 cipherSuite=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 peerCertificates=[CN=httpbin.org,CN=Amazon,OU=Server CA 1B,O=Amazon,C=US,CN=Amazon Root CA 1,C=US] localCertificates=[]}
[765 ms] connectEnd: h2
[767 ms] connectionAcquired: Connection{httpbin.org:443,proxy=DIRECT hostAddress=httpbin.org/54.147.165.197:443 cipherSuite=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 protocol=h2}
[775 ms] requestHeadersStart
[783 ms] requestHeadersEnd
[993 ms] responseHeadersStart
[994 ms] responseHeadersEnd: Response{protocol=h2,code=200,message=,url=https://httpbin.org/get}
[999 ms] responseBodyStart
[999 ms] responseBodyEnd: byteCount=267
[999 ms] connectionReleased
[1000 ms] callEnd
第二个请求可能会跳过这个,见下文,以重用连接。但在您的情况下,您希望它在建立新连接之前发出新的 DNS 请求。
[0 ms] callStart: Request{method=GET,url=https://httpbin.org/get}
[1 ms] connectionAcquired: Connection{httpbin.org:443,proxy=DIRECT hostAddress=httpbin.org/54.147.165.197:443 cipherSuite=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 protocol=h2}
[1 ms] requestHeadersStart
[1 ms] requestHeadersEnd
[98 ms] responseHeadersStart
[99 ms] responseHeadersEnd: Response{protocol=h2,url=https://httpbin.org/get}
[99 ms] responseBodyStart
[99 ms] responseBodyEnd: byteCount=267
[99 ms] connectionReleased
[99 ms] callEnd
如果它显示您在每次调用时都进行查询,那么您很可能会看到相同的行为,只是在程序中多次调用 InetAddress.getAllByName(hostname).toList()
。你希望它显示什么?