I am trying to activate a cache for offline browsing when no network is available. Unfortunatly it is somehow not working, when I debug the app, the interceptor nor cache is being accessed.
So I guess something is wrong with below code.
public class ApiHelper {
Context context;
private static final int TIMEOUT = 30;
private static final int WRITE_TIMEOUT = 30;
private static final int CONNECT_TIMEOUT = 10;
//private static final int CACHE_SIZE = 500 * 1024 * 1024;
private static final int CACHE_SIZE = 10 * 1024 * 1024;
public static final String baseUrl = "http://test.com/api-new/";
public ApiHelper(Context context) {
this.context = context;
}
private boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
// Configure access cache when offline
private final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (isNetworkAvailable(context)) {
int maxAge = 60; // read from cache for 1 minute
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
};
private static OkHttpClient CLIENT = new OkHttpClient();
File httpCacheDirectory = new File(context.getCacheDir(), "HttpCache");
Cache cache = new Cache(httpCacheDirectory, CACHE_SIZE);
{
CLIENT = new OkHttpClient.Builder().
connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
readTimeout(TIMEOUT, TimeUnit.SECONDS).
authenticator(new Authenticator()).
addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR).
cache(cache).
addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request;
UserModel user = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (user != null && user.getAccess_token() != null)
request = chain.request().newBuilder()
.addHeader("X-Auth-Token", user.getAccess_token()).build();
else
request = chain.request().newBuilder().build();
long t1 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Sending request %s on %s%n",
request.url(), chain.connection()));
UserModel currentUser = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (currentUser != null)
Logger.debug(ApiHelper.class.getName(), "Sending request header " + request.headers().toString());
if (request != null && request.body() != null && request.body().contentLength() > 0) {
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();
Logger.debug(ApiHelper.class.getName(), "Sending request body " + body);
}
Response response = chain.proceed(request);
String msg = response.body().string();
long t2 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Received response %s in %.1fms%nResponse code:%s%nReceived data: %s",
response.request().url(), (t2 - t1) / 1e6d, response.code(), msg));
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), msg))
.headers(response.headers())
.build();
}
}).build();
}
@NonNull
public static MyApplication getInstance() {
Retrofit rf = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.create()))
.client(CLIENT)
.build();
return rf.create(MyApplication.class);
}
}
You initialization block is non-static, but you never allocate an instance of this object, so it never gets run. It looks like you intended that to initialize the static member CLIENT
. Because this initialization ultimately depends on a Context
you can't convert that to a static initialization block. Convert it to an initialization method that takes a Context
parameter. Note: I also moved cache
and httpCacheDir
into this method as local variables.
private static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
// Configure access cache when offline
private static Interceptor getInterceptor(Context context) {
return new Interceptor() {
@Override
//....
}
}
private static void initClient(Context context) {
httpCacheDirectory = File(context.getCacheDir(), "HttpCache");
Cache cache = new Cache(httpCacheDirectory, CACHE_SIZE);
CLIENT = new OkHttpClient.Builder().
connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
readTimeout(TIMEOUT, TimeUnit.SECONDS).
authenticator(new Authenticator()).
addInterceptor(getInterceptor((context)).
cache(cache).
addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request;
UserModel user = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (user != null && user.getAccess_token() != null)
request = chain.request().newBuilder()
.addHeader("X-Auth-Token", user.getAccess_token()).build();
else
request = chain.request().newBuilder().build();
long t1 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Sending request %s on %s%n",
request.url(), chain.connection()));
UserModel currentUser = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (currentUser != null)
Logger.debug(ApiHelper.class.getName(), "Sending request header " + request.headers().toString());
if (request != null && request.body() != null && request.body().contentLength() > 0) {
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();
Logger.debug(ApiHelper.class.getName(), "Sending request body " + body);
}
Response response = chain.proceed(request);
String msg = response.body().string();
long t2 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Received response %s in %.1fms%nResponse code:%s%nReceived data: %s",
response.request().url(), (t2 - t1) / 1e6d, response.code(), msg));
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), msg))
.headers(response.headers())
.build();
}
}).build();
}
Then you will need to also take a Context
to you getInstance
method and then call initClient
--
@NonNull
public static MyApplication getInstance(Context context) {
initClient(context);
Retrofit rf = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.create()))
.client(CLIENT)
.build();
return rf.create(MyApplication.class);
}
You can also delete your constructor and the context
data member as they are not used.