I’m using the DefaultHTTPClient to make some HTTP GET requests. I’d like to forcefully cache all the HTTP responses for a week. After going through the docs and some SO answers, I’ve done this:
I installed an HttpResponseCache via the onCreate method of my main activity.
try {
File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) {
Log.i("dd", "HTTP response cache installation failed:" + e);
}
I added a custom HttpResponseInterceptor for my HTTP client, but I still don’t get a cache hit. Here’s my response interceptor that decompresses GZIPped content, strips caching headers and adds a custom one:
class Decompressor implements HttpResponseInterceptor {
public void process(HttpResponse hreResponse, HttpContext hctContext) throws HttpException, IOException {
hreResponse.removeHeaders("Expires");
hreResponse.removeHeaders("Pragma");
hreResponse.removeHeaders("Cache-Control");
hreResponse.addHeader("Cache-Control", "max-age=604800");
HttpEntity entity = hreResponse.getEntity();
if (entity != null) {
Header ceheader = entity.getContentEncoding();
if (ceheader != null) {
HeaderElement[] codecs = ceheader.getElements();
for (int i = 0; i < codecs.length; i++) {
if (codecs[i].getName().equalsIgnoreCase("gzip")) {
hreResponse.setEntity(new HttpEntityWrapper(entity) {
@Override
public InputStream getContent() throws IOException, IllegalStateException {
return new GZIPInputStream(wrappedEntity.getContent());
}
@Override
public long getContentLength() {
return -1;
}
});
return;
}
}
}
}
}
}
Here’s how I make my request:
String strResponse = null;
HttpGet htpGet = new HttpGet(strUrl);
htpGet.addHeader("Accept-Encoding", "gzip");
htpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1");
DefaultHttpClient dhcClient = new DefaultHttpClient();
dhcClient.addResponseInterceptor(new Decompressor(), 0);
HttpResponse resResponse = dhcClient.execute(htpGet);
Log.d("helpers.network", String.format("Cache hit count: %d", HttpResponseCache.getInstalled().getHitCount()));
strResponse = EntityUtils.toString(resResponse.getEntity());
return strResponse;
I can’t seem to pinpoint what I’m doing wrong. Would any of you know?
I failed miserably with this. According to the Android documentation, it specifically says about the
HttpResponseCache— “Caches HTTP and HTTPS responses to the filesystem so they may be reused, saving time and bandwidth. This class supports HttpURLConnection and HttpsURLConnection; there is no platform-provided cache for DefaultHttpClient or AndroidHttpClient.”So that was out.
Now Apache’s HTTP client has a
CachingHttpClientand this new version of HTTP client has been back ported to Android through this project. Of course, I could use this.I didn’t want to use the hackish version of the Apache HTTP Client libraries so one idea was to cannibalise the caching related bits from the HTTP Client and reoll my own but it was too much work.
I even considered moving to the recommended
HttpURLConnectionclass as recommended but I’ve run into other issues. There doesn’t seem to be good cookie-persistence implementation for that class.Anyway, I skipped everything and though. I’m reducing the loading time by caching, why not got go a step further and since I was using jSoup to scrape records from the page and create an
ArrayListof a custom structure, I might as well serialize the wholeArrayListby implementing theSerializablemethod on my structure. Now I don’t have to wait for the page request, not do I have to wait for the jSoup parsing slowness. Win.