i want to say that i use the okhttp caching with Retrofit but cache file not created while i write the right code because i create a sample app where is working done but when i use same code in my project i am not understood why not create cache file.
Here is my code :
private Context context;
private PrefManager prefManager;
private String BEARER = "Bearer ";
private String APP_JSON = "application/json";
private String OUTPUT_ACCEPT = "Accept";
private String AUTHERIZATION = "Authorization";
private int CACHE_SIZE_BYTES = 10 * 1024 * 1024;
private String TAG = OkHttpClientModule.class.getSimpleName();
@Provides
public OkHttpClient okHttpClient(Cache cache, Interceptor interceptor, StethoInterceptor stethoInterceptor, HttpLoggingInterceptor httpLoggingInterceptor) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(interceptor);
builder.cache(cache);
builder.connectTimeout(10, TimeUnit.SECONDS);
builder.writeTimeout(10, TimeUnit.SECONDS);
builder.readTimeout(30, TimeUnit.SECONDS);
if (BuildConfig.DEBUG) {
builder.addNetworkInterceptor(stethoInterceptor);
builder.interceptors().add(httpLoggingInterceptor);
}
OkHttpClient client = builder.build();
return client;
}
@Provides
public PrefManager getManager(Context context) {
return new PrefManager(context);
}
@Provides
public StethoInterceptor getSteltho() {
return new StethoInterceptor();
}
@Provides
public Cache cache(File cacheFile) {
Cache cache = null;
try {
cache = new Cache(cacheFile, CACHE_SIZE_BYTES);
Log.e("TAG", " cache created " + cache.directory().getPath());
} catch (Exception e) {
e.printStackTrace();
Log.e("TAG", " cache exception " + e.getLocalizedMessage());
}
return cache;
}
@Provides
@RandomUserApplicationScope
public File file(@ApplicationContext Context ctx) {
this.context = ctx;
File file = new File(ctx.getCacheDir(), "httpcache");
return file;
}
@Provides
public Interceptor getIntercepter() {
final String mAuth = "";//Credentials.basic(BaseRequest.AUTH_USERNAME, BaseRequest.AUTH_PASSWORD);
Interceptor headerAuthorizationInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
if (!NetworkUtils.isConnected(context)) {
Log.e(TAG, "response from cache ");
Request request = chain.request();
CacheControl cacheControl = new
CacheControl.Builder().maxStale(1,
TimeUnit.DAYS).build();
request = request.newBuilder().cacheControl(cacheControl).build();
String rawJson = chain.proceed(request).body().string();
Log.e(BuildConfig.APPLICATION_ID, String.format("req response cache raw JSON response is: %s", rawJson));
return chain.proceed(request);
} else {
Log.e(TAG, "response from network");
CacheControl cacheControl = new CacheControl.Builder().maxAge(1, TimeUnit.HOURS).build();
prefManager = new PrefManager(context);
String token = prefManager.getPreference(AppConstant.HEADER_TOKEN);
Request.Builder request = chain.request().newBuilder();
request.addHeader(OUTPUT_ACCEPT, APP_JSON);
request.addHeader(AUTHERIZATION, BEARER + token);
request.header(CACHE_CONTROL, cacheControl.toString());
//request.cacheControl(CacheControl.FORCE_CACHE);
Response response = chain.proceed(request.build());
return response;
}
}
};
return headerAuthorizationInterceptor;
}
@Provides
public HttpLoggingInterceptor httpLoggingInterceptor() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return httpLoggingInterceptor;
}
And i am check cache file in File explorer but showing here
You can create a Context in your MainActivity, like below:
public static Context mContext;
In your onCreate(), you can add:
mContext = getApplicationContext();
Then, in a separate file, example RetrofitCachingInstance:
public class RetrofitCachingInstance {
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = chain -> {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control",
String.format(Locale.ENGLISH, "max-age=%d", 60))
.build();
};
private static Retrofit retrofit;
private static final String BASE_URL = "YOUR_JSON_URL";
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client.addInterceptor(loggingInterceptor);
client.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR);
client.addInterceptor(provideOfflineCacheInterceptor());
client.cache(getCache(MainActivity.mContext));
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
// using Gson for deserialization in this case
.build();
}
return retrofit;
}
private static Interceptor provideOfflineCacheInterceptor() {
return chain -> {
try {
return chain.proceed(chain.request());
} catch (Exception e) {
CacheControl cacheControl = new CacheControl.Builder()
.onlyIfCached()
.maxStale(2, TimeUnit.DAYS)
// accept cached responses up to 2 days old, else hit network request again
.build();
Request offlineCachingRequest = chain.request().newBuilder()
.removeHeader("Pragma")
.cacheControl(cacheControl)
.build();
return chain.proceed(offlineCachingRequest);
}
};
}
private static Cache getCache(Context context) {
int cacheSize = 10 * 1024 * 1024; // Cache size is only 10 MB maximum
return new Cache(MainActivity.mContext.getCacheDir(), cacheSize);
}
}
This should work. Hope this is helpful.