UnknownHostException after Android 11 update

Viewed 1746

Problem: Once an UnknownHostException is returned, the user continues to receive the same error unless the app is reinstalled or the device is rebooted.

Of the users whose OS is Android 11, only a few users are having problems.

The biggest problem is that when an error occurs, the same error is returned continuously for each request.

According to users It is said that re-installing the app or rebooting the device will work again.

It seems that 99% are users of Samsung devices. Sometimes there are also Google Pixel phones.

Both Http and Https give the same error.

Both Wifi, 5G and LTE give the same error.

The request method is using POST and I don't know if it happens to GET as well, I don't use GET.

Also, either Thread is Background or Foreground, or both.

In this my code

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'

}

Create Request :


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)
        }
    }
}

Call Request (In Activity):

    ApiService.createMainWeatherApiService().getData(CustomParameter())
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(
                      { res ->
                          handleSuccess()
                      },
                      { error ->
                          // UnknownHostException!!!!
                          handleFail()
                      }
              ).apply { compositeDisposable.add(this) }

I created an issue on okhttp : https://github.com/square/okhttp/issues/6591

2 Answers

Can you include output from an event listener which will show the DNS calls that OkHttp makes (typically) using the system DNS provider?

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, O=Amazon, 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

A second request may skip this, see below, to reuse a connection. But in your case you are expecting it to make a new DNS request before establishing a new connection.

[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, code=200, message=, url=https://httpbin.org/get}
[99 ms] responseBodyStart
[99 ms] responseBodyEnd: byteCount=267
[99 ms] connectionReleased
[99 ms] callEnd

If it shows you making queries on each call, then it's likely that you would see the same behaviour just calling InetAddress.getAllByName(hostname).toList() multiple times in your program. What would you expect that to show?

Related