Question

In the documentation of HttpResponseCache there is a section:

Working With Earlier Releases

This class was added in Android 4.0 (Ice Cream Sandwich). Use reflection to enable the response cache without impacting earlier releases:

try {
    File httpCacheDir = new File(context.getCacheDir(), "http");
    long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
    Class.forName("android.net.http.HttpResponseCache")
        .getMethod("install", File.class, long.class)
        .invoke(null, httpCacheDir, httpCacheSize);
}
catch (Exception httpResponseCacheNotAvailable) {
}

You can see this call via reflection in a questions here on SO (e.g. here), and examples on the web. I also took over code that contains this exact snippet to set up the cache (including the comment, so its probably just copypasta). However, I don't quite understand why you have to use reflection here.

Normally when I want to use a method added at a certain API level above my defined minSdkVersion, I would use the following pattern:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   // do something here
}

so why isn't this the default pattern for HttpResponseCache. What is the advantage of using reflection? It certainly doesn't add to the readability of my code. Does HttpResponseCache actually work below ICS when using reflection this way?

EDIT: I don't have an old Android device here and my emulator refuses to start at all, so I can't simply test it at the moment. Maybe it just crashes horribly without reflection.

Was it helpful?

Solution

What is the advantage of using reflection?

First, quoting the documentation:

This class was added in Android 4.0 (Ice Cream Sandwich).

By "was added", they mean "was added to the Android SDK", and by "Ice Cream Sandwich", they really mean Android 3.2 (API Level 13) based on the rest of the JavaDocs.

However, the HttpResponseCache class itself has existed in the framework for longer, hopefully since Android 1.0 given their recommendations. However, that class was marked with the @hide annotation, so it could not be used directly by apps until API Level 13.

Your Java version guard block using Build will avoid referencing this class directly on older devices. However, it does not actually configure the cache on older devices, either. Their approach will work on all versions of Android and will allow you to configure the cache, as the class has existed since the beginning.

It is fairly rare that Google explicitly authorizes the use of reflection to get at hidden classes or methods this way, which is why you don't see it often in official documentation.

OTHER TIPS

Unfortunately your suggestion will not work for older versions. Think about the following. They added method install(File, long) to new version. But the code that calls this method is packaged into other jar.

Now you have old version of jar that contains HttpResponseCache and new version of jar that calls it. If you write there

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   cache.install(file, number);
}

NoSuchMethodError will be thrown even if expression of if is false. Using reflection is a ugly but useful technique to prevent this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top