Reputation: 4090
I get java.io.InterruptedIOException: timeout
rarely in my office.
However, it keeps occurring in stores.
So, I set
client.addInterceptor(httpLoggingInterceptor)
.connectTimeout(5, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
But, this didn't work.
So, What I did in .enqueue()
fun startPay(){
// ... Service Generator and so on...
override fun onFailure(call: Call<ResultData>, t: Throwable) {
when(t){
is InterruptedIOException ->{
Thread.sleep(1000)
startPay()
}
else->{
Toast.makeText(this, t.toString(), Toast.LENGTH_SHORT).show()
}
}
}
}
I am guessing this occurs because more than two clicks in short time or I am calling 3 consecutively after 200 response. ex. A call -> 200 response -> B call -> 200 response -> C call -> 200 response -> UI Update. Now, it catches the exception and retry the api call. I think this has no reason to be interrupted by the same thread or other thread..
This solution is fine in general. But the problem is when I pay something It must call just once.
this InterrupedIOException: timeout
(Not SocketTimeout) seems cancel the connection before getting the response from server, the server is sending the response well and has no problem.
Some questions in stackoverflow mentioned Crashlystics. I am using it but I shouldn't remove it.
I am using:
// Firebase
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:26.0.0')
implementation 'com.google.firebase:firebase-core'
implementation 'com.google.firebase:firebase-auth'
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-config' // remote config
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-perf'
implementation 'com.google.firebase:firebase-config-ktx'
// Network
// okhttp: https://github.com/square/okhttp
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation 'com.squareup.okhttp3:logging-interceptor:4.7.2'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation 'org.conscrypt:conscrypt-android:2.2.1' // optional
The error is here:
java.io.InterruptedIOException: timeout
W/System.err: java.io.InterruptedIOException: timeout
W/System.err: at okhttp3.internal.connection.RealCall.timeoutExit(RealCall.kt:384)
W/System.err: at okhttp3.internal.connection.RealCall.maybeReleaseConnection(RealCall.kt:346)
W/System.err: at okhttp3.internal.connection.RealCall.noMoreExchanges$okhttp(RealCall.kt:310)
W/System.err: at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:205)
W/System.err: at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:502)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
W/System.err: at java.lang.Thread.run(Thread.java:761)
W/System.err: Caused by: java.io.IOException: Canceled
W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:72)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err: at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:219)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err: at com.example.helper.api.ServiceGenerator$createService$$inlined$-addInterceptor$1.intercept(Interceptor.kt:87)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err: at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197)
W/System.err: ... 4 more
Upvotes: 5
Views: 5785
Reputation: 1143
If you still need callTimeout, you can add a custom Interceptor:
class InterruptedIOExceptionInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
return try {
chain.proceed(chain.request())
} catch (e: InterruptedIOException) {
Response.Builder()
.code(408)
.message("Request Timeout")
.protocol(Protocol.HTTP_1_1) //fixme hardcoded protocol
.request(chain.request())
.body("Request Timeout".toResponseBody("text/html".toMediaTypeOrNull()))
.build()
}
}
}
add it to the OkHttpClient.Builder:
okHttpClient.addInterceptor(InterruptedIOExceptionInterceptor())
Upvotes: 0
Reputation: 4044
One of the possible reasons is a bug in okhttp3. When you settled timeouts, POST requests can become canceled under IPv6 networks with a log like described. I am able to reproduce it using IPv6Droid application for tests (it is not free).
To fix it just remove .callTimeout()
.
Upvotes: 1