Home > Uncategorized > HTTP Response Caching for Java and Android

HTTP Response Caching for Java and Android

HTTP caching is both important, as it reduces bandwidth use and improves performance, and complex, as the rules are far from simple. In my experience, most Java and Android applications either don’t do HTTP caching, or they roll their own and up doing it wrong or in way too complicated a fashion. In other words, they create a non-standard, one off, unmaintainable solution. And IMHO, that’s no solution at all.

If you find yourself using HttpClient, you can use HttpClient-Cache, which is an easy drop in for Java. See my previous post about HttpClient-Cache for Android. But if you’re using HttpUrlConnection (aka java.net.URL.openConnection()), there’s no good solution for regular Java or Android. Well, in Android 4.0 and later, you can use HttpResponseCache, but with only a small percentage of Android devices using 4.0 or later, that’s not a terribly good solution. If you use Android 4.0+’s HttpResponseCache as recommended by Google, then all previous Android versions end up with no HTTP response caching – this causes excess load on your servers, slower performance for the app, and unnecessary bandwidth use.

To fix this problem, I grabbed all the code from AOSP that implements Android 4.0’s HttpResponseCache and made it a separate library. This library is easy to use, works on Java 1.5+, all versions of Android, and is licensed under APLv2 (just like everything else in AOSP). Really, there’s no reason not to use it! You can even use in Java server applications, such as those that use Spring.

To use it, if you’re using Maven, simply add this block to your pom.xml (all artifacts are in Maven Central):
<dependency>
<groupId>
<com.integralblue</groupId>
<artifactId>httpresponsecache</artifactId>
<version>1.0.0</version>
</dependency>

If you’re not using Maven, you’ll need to add the httpresponsecache jar and its dependency, disklrucache.jar, to your project.

When your application starts, before it makes any HTTP requests, execute this method:
com.integralblue.httpresponsecache.HttpResponseCache.install(File directory, long maxSize);
If you’re using Android, and you want to use Android 4.0’s HttpResponseCache if it’s available, and fallback to this library if it’s not available:
final long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
final File httpCacheDir = new File(getCacheDir(), "http");
try {
Class.forName("android.net.http.HttpResponseCache")
.getMethod("install", File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
} catch (Exception httpResponseCacheNotAvailable) {
Ln.d(httpResponseCacheNotAvailable, "android.net.http.HttpResponseCache not available, probably because we're running on a pre-ICS version   of Android. Using c$
try{
com.integralblue.httpresponsecache.HttpResponseCache.install(httpCacheDir, httpCacheSize);
}catch(Exception e){
Ln.e(e, "Failed to set up com.integralblue.httpresponsecache.HttpResponseCache");
}
}

The source code to the library is available on GitHub. I’m already using it in my CallerID Android app. If you end up using this library, please leave me a comment.

That’s it – enjoy easy to use HTTP caching!

Creative Commons License
HTTP Response Caching for Java and Android by Craig Andrews, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

Categories: Uncategorized Tags:
  1. Chuck Doucette
    June 13th, 2012 at 10:39 | #1
    I attempted to use HttpUrlConnection and your caching framework on top of that.
    Unfortunately, since HttpUrlConnection doesn’t work well on Android 2.3, I am forced to depend on HttpClient instead.
    HttpClient-Cache may be an easy drop-in on desktop implementations of Java – it is not an easy drop-in on Android. It depends on classes in the latest version of HttpClient that are not in the builtin Android classes and it is difficult to override them.
  2. June 13th, 2012 at 11:04 | #2
    @Chuck Doucette
    The HttpResponseCache library replaces the Android provided HttpUrlConnection implementation with the HttpUrlConnection implementation from Android 4.0. So if you’re concerned about problems that are in Android 2.3 that have been fixed in Android 4.0, then by using HttpResponseCache, you won’t have to worry about any of those possible Android 2.3 issues.

    I highly recommend that you do not use HttpClient (or HttpClient-Cache) as Android will not be maintaining its HttpClient library. Android HttpClient library has bugs that will not be fixed, and its not compatible with HttpClient-Cache as you noticed.

  3. Maziz
    August 12th, 2012 at 07:03 | #3
    Hi Craig. I tried out the code you’ve developed in Android 3.0 platform. It can be installed but when getting data from a site I built for testing, it seems it doesn’t cache the data at all. However, it does work on Android 4.x using the same site. Any suggestion?
  4. Maziz
    The thing is. There’s no error. It runs fine. I would test it by opening a web page that I serv with (max-age 60). Then I off the server and retry to connect. It is working on ICS but not on 3.x. Maybe you have any pointers on how to enable the stack trace?
  5. August 13th, 2012 at 12:17 | #6
    @Maziz
    It may be silently failing. If you look at the logcat output, you may see a stack trace. It’s possible for the cache to fail, but not affect your app in any other way than not caching.
  6. Maziz
    August 13th, 2012 at 12:29 | #7
    I’ve got the stack trace. Sent it to your email.
  7. Maziz
    August 14th, 2012 at 22:04 | #8
    @Craig Andrews
    Hi Craig.
    I’ve created an issue in git hub. The issue is issue#16. I’ve included the stack as well.
    Let me know if you need anything else.
  8. Kenny
    September 10th, 2012 at 14:18 | #9
    Hello Craig,

    I’m trying the library as a drop in replacement, I can see it is writing files to the cache I’ve set up, but I’m looking for a perf statistics and behavior to see if its working as I expect. First, is there a sample that has consistent behavior to ensure I’m using it properly?

    Secondly, despite seeing the written out cached files, the statistics reported are always zeros for network/hits/requests. I’ve tried looking at both:

    com.integralblue.httpresponsecache.HttpResponseCache.getInstalled();
    and
    com.integralblue.httpresponsecache.HttpResponseCache.getDefault();

    Both of which are non-null.

    Thoughts?

    Thanks,
    Kenny

    • September 10th, 2012 at 16:39 | #10
      Which version are you using? The was a bug in 1.0 that prevented stats from working right (they were always 0 as you described). If you upgrade to 1.2, that problem will be resolved.

      I don’t have an example project that only shows this library being used. However, if you install using com.integralblue.httpresponsecache.HttpResponseCache.install(httpCacheDir, httpCacheSize); and then look at the stats, you should see it being used. If you find a bug, please let me know! Known issues can be found and new issues reported at https://github.com/candrews/httpresponsecache

  9. Kenny
    September 11th, 2012 at 09:44 | #11
    I started with the binaries, but now I’m building from the latest source from GitHub, I’ve added an optional logging interface to try to figure out what is and isn’t getting cached. I’ll let you know what I find. Thx.
  10. Sourabh Deshpande
    October 10th, 2012 at 02:01 | #12
    I am using the this library on android 4.0 but I am getting the IllegalAccessError while creating the HttpUrlConnection object. I tried using the following code

    final long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
    final File httpCacheDir = new File(getCacheDir(), “http”);
    try {
    Class.forName(“android.net.http.HttpResponseCache”)
    .getMethod(“install”, File.class, long.class)
    .invoke(null, httpCacheDir, httpCacheSize);
    } catch (Exception httpResponseCacheNotAvailable) {
    Ln.d(httpResponseCacheNotAvailable, “android.net.http.HttpResponseCache not available, probably because we’re running on a pre-ICS version of Android. Using c$
    try{
    com.integralblue.httpresponsecache.HttpResponseCache.install(httpCacheDir, httpCacheSize);
    }catch(Exception e){
    Ln.e(e, “Failed to set up com.integralblue.httpresponsecache.HttpResponseCache”);
    }
    }

    But in ICS I am getting the HttpResponseCache.getInstalled() returning null. If i use this library on pre ICS version its working fine. Please provide any suggestion to make it work on ICS as well.

  11. Luke
    November 28th, 2012 at 15:10 | #13
    You say “The HttpResponseCache library replaces the Android provided HttpUrlConnection implementation with the HttpUrlConnection implementation from Android 4.0.” but it’s unclear how to use HttpResponseCache’s version of HttpUrlConnection. I found HttpURLConnectionImpl, but it is not visible to external packages.
  12. Luke
    November 28th, 2012 at 16:03 | #15
    Ah, ok.

    It wasn’t clear if using the built in version would take advantage of the cache and the fixes to issues in older versions.

    Thanks for the help and the great library.

  1. No trackbacks yet.