OkHttp caching not working when there's internet or not

I'm trying to Make the application uses caching with Okhttp and Retrofit, so the problem that I have now is when I'm using **CacheInterceptor to cache the data** it is getting the data from the internet, and When I'm using **ForceCacheInterceptor to get the data offline** with it, it is not showing any data Whether there is Internet available or not. It is supposed to display Data if there is no Internet, but strange it is not displaying any Data whether there is an Internet or not when used.

So how can I fix this problem, Here's my code


My CacheInterceptor to cache the data

class CacheInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
    val response: Response = chain.proceed(chain.request())
    lateinit var context: Context
    return response.newBuilder()
        .removeHeader("Pragma")
        .removeHeader("Cache-Control")
        .header(
            "Cache-Control",
            if (CheckNetwork.isInternetAvailable(context)) "public, max-age=60" else "public, only-if-cached, max-stale=604800"
        )            .build()
}

}


My ForceCacheInterceptor to get the data offline

class ForceCacheInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
    val builder: Request.Builder = chain.request().newBuilder()
    lateinit var context: Context
    if (!CheckNetwork.isInternetAvailable(context)) {
        builder.cacheControl(CacheControl.FORCE_CACHE);
    }
    return chain.proceed(builder.build());
  }
}

My NetworkLayer, Here I'm using OKhttp and retrofit

class NetworkLayer : AppCompatActivity() {

private val BASE_URL = ""
private val moshi: Moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
private val myHttpClient = OkHttpClient()

override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
    super.onCreate(savedInstanceState, persistentState)
    val interceptor = HttpLoggingInterceptor()
    interceptor.level = HttpLoggingInterceptor.Level.BODY

    val httpCacheDirectory = File(applicationContext.cacheDir, "http-cache")
    val cacheSize = 10 * 1024 * 1024 // 10 MiB
    val cache = Cache(httpCacheDirectory, cacheSize.toLong())

    myHttpClient
        .newBuilder()
        .addNetworkInterceptor(CacheInterceptor())
        .addInterceptor(ForceCacheInterceptor())
        .cache(cache)
        .callTimeout(3, TimeUnit.SECONDS)
        .connectTimeout(3, TimeUnit.SECONDS)
        .build()
}

private val retrofit: Retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(myHttpClient)
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

val apiService: APIService by lazy {
    retrofit.create(APIService::class.java)
   }
}

And latest my check network class

object CheckNetwork {
private val TAG = CheckNetwork::class.java.simpleName
fun isInternetAvailable(context: Context): Boolean {
    val info =
        (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
    return if (info == null) {
        Log.d(TAG, "no internet connection")
        false
    } else {
        if (info.isConnected) {
            Log.d(TAG, " internet connection available...")
            true
        } else {
            Log.d(TAG, " internet connection")
            true
        }
    }
  }
}

Solution 1:

As you said, the ForceCacheInterceptor forces to use cache, even when an internet connection is available. !CheckNetwork.isInternetAvailable(context) will evalue to true and force cache.

If no cache is available, then no data can be displayed, regardless of connectivity.
To resolve this issue, you have to cache data once, to be able to retrieve it when there's no internet connection.

Note: You cannot cache data, when no chace header is present: (e.g. Cache-Control: public or Cache-Control: max-age=3600)

In case your response does not provide those headers, you have to add/modify them yourself.
Note: Doing so violates the decision by the author of the data and you should consider warning the user that the data is stale.