Home > Enterprise >  How to stop Retrofit OkHttp request from .addNetworkInterceptor only and should return to onSuccess
How to stop Retrofit OkHttp request from .addNetworkInterceptor only and should return to onSuccess

Time:03-09

Flow: I want to check Internet connection when Retrofit makes API call, and if there is no internet connection, then I don't want to proceed further and my request should cancel. Please very clearly note that, I saw many many post related to this, but most of are doing when retrofit is completing the request and it is going in onFailure, there people are handling Internet connection check. I do not want that. I want to make architecture for all my api call in a single place where my all api's call will check Internet connection first then only it will proceed, otherwise it will return and it should go simply in onfailure.

Let me explain my problem with code:

This is my OkHttp functionality which I provide through Hilt:

    ......
okHttpClientBuilder.addNetworkInterceptor(NetworkInterceptor())
            okHttpClientBuilder.addInterceptor(logger)
            okHttpClientBuilder.authenticator(refreshTokenAuthenticator)
            okHttpClientBuilder.addInterceptor(AuthInterceptor(context, tokenProvider))
....

Point to be noted that, I used .addNetworkInterceptor for my NetworkInterceptor class, and for other Interceptors, like AuthInterceptor, where I'm appending headers, there I used .addInterceptor

NetworkInterceptor

class NetworkInterceptor: Interceptor {
    //TODO: temp hardcoded to test the functionality
    private val isNetworkActive = false

    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()


        if (isNetworkActive) {
            return chain.proceed(request).newBuilder().build()
        } else {
            chain.call().cancel()
            return chain.proceed(chain.request());
        }
    }
}

So, basically it is going to else condition, please correct my else condition if anything is wrong. Also people are throwing an exception from here, but that will not work in my case, because the thing is, after going from else condition, it is going to AuthInterceptor class. I tried to modified sequence / statement of above and down (like first auth and then network one..), but in all cases it is going to my AuthInterceptor. The one reason, I feel is because .addNetworkInterceptor called first and then .addInterceptor even though it is written in any sequence!

this sequence:

okHttpClientBuilder.addNetworkInterceptor(NetworkInterceptor())
        okHttpClientBuilder.addInterceptor(logger)
        okHttpClientBuilder.authenticator(refreshTokenAuthenticator)
        okHttpClientBuilder.addInterceptor(AuthInterceptor(context, tokenProvider)) 

AuthInterceptor

class AuthInterceptor @Inject constructor(private val context: Context, private val tokenProvider: ILocalTokenProvider) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val requestBuilder = chain.request().newBuilder()
        //TODO remove context also from constructor
        requestBuilder.header(AppConstants.INetworkValues.AUTHORIZATION, tokenProvider.getAccessToken() ?: "")
        return chain.proceed(requestBuilder.build())
    }
}

So, if you see my return statement there app is crashing with this: java.io.IOException: Canceled

Also what I want is that if I'm cancelling my req from network intercptor then I don't want to go in other interceptors, it should return and I should get failure in retrofit callback.

Any help would be really appreciated, like I'm trying this basic problem from last few days.

CodePudding user response:

The key part is to check the connectivity statusapplication Interceptor and throw an IOException before any connection is attempted. network interceptors must proceed exactly once.

See https://square.github.io/okhttp//features/interceptors/#choosing-between-application-and-network-interceptors

Then make sure you handle that exception gracefully in the caller.

Or return a dummy or cached result when network is not available.

As you are already doing, you need to either hook into the ConnectivityManager yourself,

Something like https://github.com/Petrulak/android-kotlin-mvp-clean-architecture/blob/master/app/src/main/java/com/petrulak/cleankotlin/platform/connectivity/ConnectivityChecker.kt

or use a library like

https://github.com/erikhuizinga/flomo

CodePudding user response:

This is the correct answer, basically we should throw an Exception from Interceptors, and whatever is the next "response-receiving layer" for example activity, fragment, repository, viewmodel, remotedatasource. In my case next layer is remotedatasource, so I catch the exception there.

See this answer:

https://stackoverflow.com/a/58905082/14016240

  • Related