Open In App

OkHttp Interceptor in Android

Last Updated : 14 Sep, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Interceptors, according to the documentation, are a powerful mechanism that can monitor, rewrite, and retry the API call. So, when we make an API call, we can either monitor it or perform some tasks. In a nutshell, Interceptors function similarly to airport security personnel during the security check process. They checked our boarding pass, stamped it, and then let us pass. We can use interceptors to do a variety of things, such as centrally monitoring API calls. In general, we need to add a logger for each network call, but by using the interceptor, we can add a logger once and it will work for all network calls. Another use-case is caching the response of network calls to build an offline-first app, which we will cover in detail later in this blog.

Interceptor Types

Interceptors are classified into two types:

  1. Interceptors added between the Application Code (our written code) and the OkHttp Core Library are referred to as application interceptors. These are the interceptors that we add with addInterceptor().
  2. Interceptors on the network: These are interceptors placed between the OkHttp Core Library and the server. These can be added to OkHttpClient by using the addNetworkInterceptor command ().

How do you include interceptors in OkHttpClient?

We can add the interceptor while building the OkHttpClient object, as shown below:

Kotlin




fun gfgHttpClient(): OkHttpClient {
     val builder = OkHttpClient().newBuilder()
         .addInterceptor(/*our interceptor*/)
     return builder.build()
 }


In addInterceptor, we can include the MyInterceptor (). Now, let’s look at some more real-world applications for Interceptors.

  1. Real-world applications of Interceptors
  2. The following are some of the most common use-cases in Android:
  3. Centralized error logging

First, we must construct the ErrorInterceptor as shown below:

Kotlin




class gfgInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val aRequest: Request = chain.request()
        val aResponse = chain.proceed(request)
        when (response.code()) {
            400 -> {
                // Show Bad Request Error Message
            }
            401 -> {
                // Show UnauthorizedError Message
            }
 
            403 -> {
                // Show Forbidden Message
            }
 
            404 -> {
                // Show NotFound Message
            }
 
            // ... and so on
        }
        return response
    }
}


  1. First, we obtain the request from the chain. request()
  2. The response from the server is then obtained by passing the request through the chain.
  3. Proceed(request) At this point, we can check for the response code and take action.
  4. Pass this and wait for the results

Assume we receive a 401 error, i.e. Unauthorized, and we can perform an action to clear the app data/log out the user or any other action we desire.

This is how we can use the Interceptor to create a centralized Error Logger.

OkHttp includes a logger, which is extremely useful for debugging.

GeekTip #1:  If we want to log the details of URL redirection, consider using an interceptor at the network layer with the addNetworkInterceptor command ().

Keeping the response in the cache

If we want to cache the API call response so that when we call the API again, the response will come from Cache. If we have an API call from Client to Server and the Cache-Control header is enabled on the server, OkHttp Core will respect that header and cache the response that was sent from the server for a certain amount of time. But what if the server does not enable Cache-Control? Using Interceptor, we can still cache the response from OkHttp Client.

Just look at the image above. What we need to do here is intercept the Response before entering OkHttp Core and add the header (Cache-Control), so that it is treated as if the response (with the Cache-Control header) has come from the server, and OkHttp Core will respect that and cache the response.

Kotlin




class gfgCache : Interceptor {
    override fun someInter(chain: Interceptor.Chain): Response {
        val aResponsive: Response = chain.proceed(chain.request())
        val someCache = CacheControl.Builder()
            .maxAge(12, TimeUnit.DAYS)
            .build()
        return response.newBuilder()
            .header("Geeks for Geeks Cache", cacheControl.toString())
            .build()
    }
}


As we can see, we are not using addInterceptor() in this case, but rather addNetworkInterceptor(). This is due to the fact that the operation is taking place at the network layer in this case. But there is one thing we must keep in mind while developing the offline-first app. Because OkHttp is designed in this manner, the cached response will be returned only when the Internet is available. It returns data from the cache when the Internet is available and data is cached. Even if the data is cached and the Internet is unavailable, the error “no internet available” is returned.

What should I do now?

In addition to the one mentioned above, we can use the ForceCacheInterceptor listed below at the Application layer (CacheInterceptor, only if not enabled from the server). In order to implement this in code, we will create a ForceCacheInterceptor as shown below:

Kotlin




class aGeeksforGeeksForce : Interceptor {
    override fun someIntercept(chain: Interceptor.Chain): Response {
        val aRandomBuilder: Request.Builder = chain.request().newBuilder()
        if (!IsInternetAvailable()) {
              // Check internet
            builder.someIntercept(CacheControl.FORCE_CACHE);
        }
        return chain.proceed(builder.build());
    }
}


Because we want the ForceCacheInterceptor to work on the Application layer, we add it to OkHttpClient using addInterceptor() rather than addNetworkInterceptor().

Adding a Header, such as an Access Token, in a central location

Assume we need to make API calls and include the Authorization Header in all of them. We can use it individually or we can use the Interceptor to centralize it.

Kotlin




class someGfgAuth : Interceptor {
    override fun aRandomCheck(chain: Interceptor.Chain): Response {
        val theOriginals = chain.request()
        val theBuilders = originalRequest.newBuilder()
            .header("GeeksforGeeks", "Auth")
        val spandan = requestBuilder.build()
        return chain.proceed(request)
    }
}


  1. First, we retrieve the header token from our local storage using a SharedPreference.
  2. In this section, we intercept the original request that we triggered from the application using chain.
  3. request() and set the parameter to originalRequest.
  4. The request is then rebuilt by including the Header with the key and value required to make the network call.
  5. Then, we’ll rebuild the request and use the chain to return the response.
  6. proceed(request) by passing a new request with the Authorization header.

Refreshing the Access Token in a Single Location

Assume we have a use-case in which we receive a 401 error in the Error Interceptor and need to refresh the auth token due to an Unauthorized error. We can accomplish this by utilizing the following:

Kotlin




override fun gfgInter(chain: GfgInteror.Chain): Response {
    val gfgAuthToken = // our access Token
    val ourRequest = chain.ourRequest().newBuilder()
        .addHeader("Authorization", gfgAuthToken)
        .build()
    val response = chain.proceed(ourRequest)
    if (response.code() == 401) {
            val newToken: String =
            if (newToken != null) {
               val newOurRequest =  chain.ourRequest().newBuilder()
                    .addHeader("GFGAuth", newToken)
                    .build()
                return chain.proceed(newOurRequest)
            }
    }
    return response
}


GeekTip#2: : Another method for refreshing the Access Token that is more flexible is to use OkHttp’s Authenticator interface.

Let’s move on to another use case.

Gzip Enabling at the Android End

Gzip is a data compression program. Using the interceptor, we can also use Gzip for compression in Android. So, when receiving a response, OkHttp automatically respects the header (content encoding) and decompresses the data before returning; however, if we need to send compressed data to a server, we must write our own interceptor.

Kotlin




.addAGFGInterceptor(GzipRequestInterceptor())




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads