Android Http Client Caching
android, apache-httpclient-4.x, caching
Solution
The page you are loading specifies a `Expires:Sat, 01 Jan 2000 00:00:00 GMT` header, i.e. it's always considered stale and must always be re-fetched.
Edit:
Also returns a `Pragma: no-cache` apparently. Basically, it's telling your HTTP client to never cache this page. You may be able to remove these headers with a HttpResponseInterceptor if you're dead-set on caching the response.
#2 Edit:
Using `http-clientcache-4.2.jar` is going to be problematic as it is not completely compatible with the version of the HTTP client packaged with the Android SDK - you're going to get `NoClassDefFoundError`s and similar nonsense when using it.
However - if you "build-your-own" by downloading the source for clientcache-4.2 and strip out any unfulfilled references (such as refactoring the package name of the commons logging) & killing of all the annotations sprinkled throughout the code (etc.) you can probably get a working version. If you do, this worked:
class MakeCacheable implements HttpResponseInterceptor {
public static MakeCacheable INSTANCE = new MakeCacheable();
public void process(HttpResponse resp, HttpContext ctx) throws HttpException, IOException {
resp.removeHeaders("Expires");
resp.removeHeaders("Pragma");
resp.removeHeaders("Cache-Control");
}
}
Injected into the `DefaultHttpClient` used by the `CachingHttpClient` like so:
DefaultHttpClient realClient = new DefaultHttpClient();
realClient.addResponseInterceptor(MakeCacheable.INSTANCE, 0); // This goes first
CachingHttpClient httpClient = new CachingHttpClient(realClient, cacheConfig);
If an entry is cached or not is decided by the `ResponseCachingPolicy` which unfortunately is a `final` in the `CachingHttpClient`, but looking through it will show all the headers that need to go to make an un-cacheable entry cacheable.
Problem
In my android application I am trying to cache the response of Http Client. I am testing this task using facebook graph api and have the following url: https://graph.facebook.com/riz.ahmed.52 For the first time I get the "first_name" and display it. Then I change the First Name of my facebook profile and call the same link again. I am expecting to get the old/cached "first_name" but I get the updated one. The console always shows the "The response came from an upstream server" message when I call the url. My code for Http Client is as follows: ``` CacheConfig cacheConfig = new CacheConfig(); cacheConfig.setMaxCacheEntries(1000); cacheConfig.setMaxObjectSizeBytes(8192); //HttpClient httpclient = new CachingHttpClient(new DefaultHttpClient(), cacheConfig); DefaultHttpClient httpclient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); // Updated code [START] httpclient.addResponseInterceptor(new HttpResponseInterceptor() { public void process( final HttpResponse response, final HttpContext context) throws HttpException, IOException { response.removeHeader(response.getFirstHeader("Pragma")); response.removeHeader(response.getFirstHeader("Expires")); } }); // Updated code [END] HttpGet httpget = new HttpGet(url); // Execute HTTP Get Request HttpResponse response = httpclient.execute(httpget, localContext); HttpEntity entity = response.getEntity(); String res = EntityUtils.getContentCharSet(entity); CacheResponseStatus responseStatus = (CacheResponseStatus) localContext.getAttribute( CachingHttpClient.CACHE_RESPONSE_STATUS); switch (responseStatus) { case CACHE_HIT: System.out.println("A response was generated from the cache with no requests " + "sent upstream"); break; case CACHE_MODULE_RESPONSE: System.out.println("The response was generated directly by the caching module"); break; case CACHE_MISS: System.out.println("The response came from an upstream server"); break; case VALIDATED: System.out.println("The response was generated from the cache after validating " + "the entry with the origin server"); break; } ``` I am using Android 2.3.3. Please let me know what I am missing here