Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OkHttp3 Never Timeout on slow internet

First of all, I have read so many questions regarding my question but it never gives me the solution. Here are some of the questions which I read regarding my question.

  • Question 1
  • Question 2
  • Qusetion 3
  • Question 4
  • Question 5
  • Question 6
  • Question 7

I also read this article regarding my question but it also never provide me the solution.

Problem:

I am using Okhhtp3 library in my application for Web Services. It's working fine but when the internet connection slow or unreliable connection it's stuck and never times out or never calls the timeout exception or failure method.

Here is the client code:

OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)
            .writeTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20, TimeUnit.SECONDS)
            .retryOnConnectionFailure(false)
            .build();

How can get the timeout exception or called failure method after 20 secs?

Please help me. Thanks

like image 254
Tanveer Munir Avatar asked Mar 12 '19 13:03

Tanveer Munir


People also ask

How do I increase timeout in OkHttp?

By default, for the OkHttpClient, this timeout is set to 10 seconds. However, we can easily change its value using the OkHttpClient. Builder#connectTimeout method. A value of zero means no timeout at all.

Is OkHttp asynchronous?

OkHttp doesn't currently offer asynchronous APIs to receive a response body in parts.

What is the use of okhttp3?

OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications. It comes with advanced features, such as connection pooling (if HTTP/2 isn't available), transparent GZIP compression, and response caching, to avoid the network completely for repeated requests.

What is write timeout?

The write timeout it is the maximum time you allow to write (send) the request data to the service. If you have a very short request body, it will probably be sent in a matter of milliseconds to the server. However, if you POST a very large file to an API, it might take severall seconds on a 3G network.


1 Answers

As pointed out by Trevor Halvorson, you could set callTimeout during client builder, in this way:

OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)
            .callTimeout(20, TimeUnit.SECONDS)
            .writeTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20, TimeUnit.SECONDS)
            .retryOnConnectionFailure(false)
            .build();

I've personally tested in a dummy project using version 3.14.0 of okhttp3:

implementation 'com.squareup.okhttp3:okhttp:3.14.0'

And setting a timout of 5 seconds and my emulator connection to GPRS and Poor connectivity I get

java.net.SocketExcpetion: Socket closed: timeout

enter image description here

This is my full dummy activity:

package com.example.shadowsheep.myapplication;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.concurrent.TimeUnit;

import androidx.appcompat.app.AppCompatActivity;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView helloTextView = findViewById(R.id.helloTextView);

        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)
                .callTimeout(5, TimeUnit.SECONDS)
                .writeTimeout(5, TimeUnit.SECONDS)
                .readTimeout(5, TimeUnit.SECONDS)
                .retryOnConnectionFailure(false)
                .build();

        Request request = new Request.Builder()
                .url("https://www.versionestabile.it/blog")
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
                Log.d("OKHTTP3", e.getMessage());
                // You get this failure
                runOnUiThread(() -> helloTextView.setText("TIMEOUT - FAILURE -> " + e.getMessage()));
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    final String _body = response.body().string();
                    Log.d("OKHTTP3", _body);
                    runOnUiThread(() -> {
                        helloTextView.setText(_body);
                    });
                } catch (InterruptedIOException e) {
                    runOnUiThread(() -> {
                        // Or this exception depending when timeout is reached
                        helloTextView.setText("TIMEOUT EXCEPTION->"+ e.getCause() + ": " + e.getMessage());
                    });
                }
            }
        });
    }
}

I'll give you also my app build.gradle file.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.shadowsheep.myapplication"
        minSdkVersion 24
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.2-alpha02'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'

    implementation 'com.squareup.okhttp3:okhttp:3.14.0'
}
like image 80
shadowsheep Avatar answered Sep 29 '22 09:09

shadowsheep