Android web dev mess: async requests for files in offline cache fail

In this instalment, Android 3.x strikes again. I guess Android developers forgot to check for regressions because it’s once again a bug not present in Android 2.x.

So, I have an application where I wanted to be nice to the users and used the offline cache to make sure they don’t download any more files than they absolutely have to. It works well (although offline manifests have plenty of… quirks of their own) - until you try to run the app on an Android 3.x device.

I also used jQuery Mobile, which retrieves HTML pages asynchronously and adds them to the DOM. On one of these 3.x devices, these requests mysteriously fail, and the error callback is fired. Naturally, I spent a few hours checking things like web server configuration and searching for a cross-section of problems with caching and jQuery Mobile.

I finally figured out that the request was actually succeeding, but instead of response code 200 it was producing 0, thus triggering the jQuery error callback. I’m using jQuery 1.7.1 (it’s old but c’est la vie) so this issue may be fixed in later versions - I haven’t checked. However, I have checked that jQuery Mobile 1.3 doesn’t address this issue in its loadPage method.

By the way, there is an excellent article which describes a lot of offline cache gotchas, including this one:

My solution, adapted from this article, was to check for the 0 response code along with a few other things in the error callback, and to call the success callback if it looks like the request succeeded:

error: function (request, textStatus, error) {
    if (request.statusText !== 'abort' && request.status == 0 && 
        request.responseText !== undefined && request.responseText) {

               successHandler(xhr.responseText, textStatus, xhr);
           // ... rest of error handler