Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Okhttp always retrying failed connection

If I create a request and that request returns a 4xx error Retrofit/Okhttp keeps retrying the request. I have set retryOnConnectionFailure to false and set a timeout of 15 seconds but that all seems to be ignored. did I miss something?

private static OkHttpClient getClient() {
        return new OkHttpClient.Builder()
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE))
                .readTimeout(15, TimeUnit.SECONDS)
                .connectTimeout(15, TimeUnit.SECONDS)
                .retryOnConnectionFailure(false)
                .addInterceptor(chain -> {
                    Request request = chain.request()
                            .newBuilder()
                            .build();

                    return chain.proceed(request);
                }).build();
    }

    public static Retrofit getRetrofitClient(Gson gson){
        Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(OkHttpLogger.getClient());
        if(gson != null){
            builder.addConverterFactory(GsonConverterFactory.create(gson));
        }else{
            builder.addConverterFactory(GsonConverterFactory.create());
        }

        return builder.build();
    }

I am using retrofit 2.3.0 and okhttp version 3.8.1

Edit

One thing I do see is that if I set a timeout of 5 seconds it works perfectly keeps retrying for 5 seconds then gives me a failure but if I bump it up to 10 seconds it just keeps going and finally stops around 2 minutes.

like image 431
tyczj Avatar asked Jul 07 '17 20:07

tyczj


3 Answers

The issue is that retryOnConnectionFailure does not apply to 408 responses so it will still retry those automatically

like image 68
tyczj Avatar answered Oct 23 '22 11:10

tyczj


This code may help you, I use Retrofit in Application Class and use that class in Manifest file as application name tag

public final class Application extends MultiDexApplication {

public static Retrofit retrofit;
public static String base_URL = "http://mds.devsiteurl.com/";

public static final String TAG = Application.class.getSimpleName();

private static Application mInstance;

public static synchronized Application getInstance() {
    return mInstance;
}
@Override
public void onCreate() {
    super.onCreate();

    mInstance = this;
    MultiDex.install(this);

    Gson gson = new GsonBuilder()
            .setLenient()
            .create();

    final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .readTimeout(15, TimeUnit.SECONDS) 
            .connectTimeout(15, TimeUnit.SECONDS)
            .build();

    retrofit = new Retrofit.Builder()
            .baseUrl(base_URL)
            .client(okHttpClient)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();
}
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}
}

And in Manifest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mds.foundation.mdsfoundation">

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:name=".Application"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_apis_keys" />

    <activity android:name=".activity.MainActivity" />
    <activity
        android:name=".activity.CenterOfExcellenceActivity"
        android:windowSoftInputMode="adjustPan" />
    <activity android:name=".activity.SplashScreenActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

</manifest>

And finally gradle.build

apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
    applicationId "com.mds.foundation.mdsfoundation"
    minSdkVersion 19
    targetSdkVersion 25
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    multiDexEnabled true  //this line is important
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
packagingOptions {

    exclude 'META-INF/DEPENDENCIES.txt'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/notice.txt'
    exclude 'META-INF/license.txt'
    exclude 'META-INF/dependencies.txt'
    exclude 'META-INF/LGPL2.1'
}
useLibrary 'org.apache.http.legacy'
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
compile('org.apache.httpcomponents:httpmime:4.3.6') {
    exclude module: 'httpclient'
}
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.1'

//refrofit 
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.android.support:multidex:1.0.1'
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.picasso:picasso:2.5.2'
testCompile 'junit:junit:4.12'
}
like image 22
Shreeya Chhatrala Avatar answered Oct 23 '22 10:10

Shreeya Chhatrala


you can try creating your own retryOnConnectionFailure interceptor:

here is code in kotlin:

open class MaxRetryCountInterceptor(private val retryLimit: Int) : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Chain): Response {
        val request = chain.request()
        var response = chain.proceed(request)
        var tryCount = 0

        while (!response.isSuccessful && tryCount < retryLimit) {
            tryCount++
            response = chain.proceed(request)
        }

        return response
    }
}

response.isSuccessful is successful only when code is between 200..300

like image 1
Antonis Radz Avatar answered Oct 23 '22 10:10

Antonis Radz