12

Hi I am trying to use the HttpResponseCache introduced in Android 4.The docs do talk clearly about how to install the cache but I am at a complete loss on how to cache Images downloaded from the net.Earlier I was using the DiskLruCache to cache them. Would anyone point me towards some examples of working code where HttpResponseCache has been used..

Edit:- Can someone tell me what I am doing wrong here:-

MainActivity.java
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    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);
        Log.v(TAG,"cache set up");
    } catch (Exception httpResponseCacheNotAvailable) {
        Log.v(TAG, "android.net.http.HttpResponseCache not available, probably because we're running on a pre-ICS version of Android. Using com.integralblue.httpresponsecache.HttpHttpResponseCache.");
        try{
            com.integralblue.httpresponsecache.HttpResponseCache.install(httpCacheDir, httpCacheSize);
        }catch(Exception e){
            Log.v(TAG, "Failed to set up com.integralblue.httpresponsecache.HttpResponseCache");
        }
    }
    TheMainListFrag gf=(TheMainListFrag) getSupportFragmentManager().findFragmentByTag("thelistfrags");
    if(gf==null){
        gf=TheMainListFrag.newInstance();
        FragmentTransaction ft=getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.thelefty, gf,"thelistfrags");
        ft.commit();
    }
}

Then in the loader of TheMainListFrag, I do the below:-

public ArrayList<HashMap<String,String>> loadInBackground() {
    String datafromServer = null;
    ArrayList<HashMap<String,String>> al = new ArrayList<HashMap<String,String>>();
    try {
        String url = "someurl";
        HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();

        urlConnection.setRequestProperty("Accept", "application/json");
        InputStream is = new BufferedInputStream(urlConnection.getInputStream());
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        datafromServer=sb.toString();
        Log.v("fromthread",datafromServer);
        // etc 
                    //etc

    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (Exception e) {
        Log.v("fromthread", e.getClass() + "--" + e.getMessage());
    }

    return al;
}

When i am connected to internet, it works fine, and in the directory http-the cache directory named above, i can see the files too. But when I am not connected to the internet, the data refuses to load.

When i load images from the net, i see the cache files named as .tmp , which i believe are termed as dirty as per DiskLruCache.

Please let me know if there is any other info that you want me to provide

3
  • HttpResponseCache only works with Http(s)URLConnection. Are you using these calls? Here's an example: developer.android.com/reference/android/net/http/… Commented Jul 20, 2012 at 18:22
  • Yup all done exactly like that.. I am even using candrews library for backporting ..I see that json responses are getting cached but am unable to cache Bitmaps...
    – Rasmus
    Commented Jul 20, 2012 at 18:25
  • Why are you using reflection? Commented Feb 13, 2018 at 15:15

3 Answers 3

11

From the section Force a Cache Response on the HttpResponseCache documentation:

Sometimes you'll want to show resources if they are available immediately, but not otherwise. This can be used so your application can show something while waiting for the latest data to be downloaded. To restrict a request to locally-cached resources, add the only-if-cached directive:

try {
    connection.addRequestProperty("Cache-Control", "only-if-cached");
    InputStream cached = connection.getInputStream();
    // the resource was cached! show it
} catch (FileNotFoundException e) {
    // the resource was not cached
}

This technique works even better in situations where a stale response is better than no response. To permit stale cached responses, use the max-stale directive with the maximum staleness in seconds:

int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
connection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);
4
  • Thanks Jesse.. That did the job... However when I download images from the net they are shown with .tmp extension. This does not seem to happen when I use the DiskLruCache directly.
    – Rasmus
    Commented Jul 30, 2012 at 8:26
  • will using the HttpResponseCache use heap memory or native memory? Commented Oct 21, 2013 at 10:18
  • +1. In my case, just setting max-stale in the requests fixed the situation that nothing was actually read from HttpResponseCache.
    – Jonik
    Commented Oct 31, 2013 at 16:31
  • 1
    Hmm, actually connection.setUseCaches(true); was sufficient for me.
    – Jonik
    Commented Oct 31, 2013 at 16:53
1

When you enable HttpResponseCache, all HttpUrlConnection queries will be cached. You can't use it to cache arbitrary data, so I'd recommend keep using DiskLruCache for that.

6
  • HttpResponseCache does not work with HttpClient.It works with HttpUrlConnection. Yes It automatically caches all my json etc.. But Does the HttpResponseCache implementation not use the DiskLruCache internally. If so cant it be used to cache Bitmaps too
    – Rasmus
    Commented Jul 20, 2012 at 18:24
  • 1
    Yes, I'm sorry - I shouldn't have typed it just from memory. What I meant is that actual Bitmap objects aren't stored in the cache. However, HTTP requests for images should be cached, if that's what you mean. Corrected my answer. Commented Jul 20, 2012 at 18:44
  • Could you please elaborate a little more on -->"When you enable HttpResponseCache, all HttpUrlConnection queries will be cached"..
    – Rasmus
    Commented Jul 20, 2012 at 18:49
  • 1
    If you install the HttpResponseCache, it will cache all responses that you get using HttpUrlConnection. That means that when you make the same request again, you can get a cached response immediately, without even sending anything over the network. Commented Jul 20, 2012 at 18:56
  • The images I am talking of are the ones which are obtained from the HttpUrlConnection, I mean they are being downloaded from the net. It is not arbitrary data
    – Rasmus
    Commented Jul 21, 2012 at 6:55
1

In my case HttpResponseCache wasn't actually caching anything. What fixed it was simply:

connection.setUseCaches(true);

(This must be called on the HttpURLConnection before establishing connection.)

For finer grained control, max-stale can be used as Jesse Wilson pointed out.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.