3

Is there a way to cache the AJAX responses received in the WebView to be cached for offline use?

I have cached the page and all its resources using some of the webveiw settings and most importnant:

        ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Activity.CONNECTIVITY_SERVICE);
    if (cm.getActiveNetworkInfo() == null || !cm.getActiveNetworkInfo().isConnected()) {
        wvContent.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    } else {
        wvContent.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
    }

But in my client's page, that I cached, there are some AJAX calls which responses I want co cache for offline use? Is there a way to achieve that?

1 Answers1

1

In order to achieve this you have to implement two things.

1) a way to catch the Ajax response and cache it. 2) a way to serve the cached result on an ajax request.

Part #1 You can use a JavascriptInterface and jQuery to catch the AJAX response. Look here for an example how to use the JavascriptInterface. After that you can cache the response

Part #2 (or 1 & 2) You can serve the cached content using the shouldInterceptRequest method of WebViewClient. Look here for an example. In the example you can combine the #part 1 and make a network call to fetch the Ajax response manually.

Here is an example you can work with.

     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     @Override
     public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        Log.i(TAG,"shouldInterceptRequest path:"+request.getUrl().getPath());
        WebResourceResponse returnResponse = null;
        if (request.getUrl().getPath().startsWith("/cart")) { // only interested in /cart requests
            returnResponse = super.shouldInterceptRequest(view, request);
            Log.i(TAG,"cart AJAX call - doing okRequest");
            Request okRequest = new Request.Builder()
                    .url(request.getUrl().toString())
                    .post(null)
                    .build();
            try {
                Response okResponse = app.getOkHttpClient().newCall(okRequest).execute();
                if (okResponse!=null) {
                    int statusCode = okResponse.code();
                    String encoding = "UTF-8";
                    String mimeType = "application/json";
                    String reasonPhrase = "OK";
                    Map<String,String> responseHeaders = new HashMap<String,String>();
                    if (okResponse.headers()!=null) {
                        if (okResponse.headers().size()>0) {
                            for (int i = 0; i < okResponse.headers().size(); i++) {
                                String key = okResponse.headers().name(i);
                                String value = okResponse.headers().value(i);
                                responseHeaders.put(key, value);
                                if (key.toLowerCase().contains("x-cart-itemcount")) {
                                    Log.i(TAG,"setting cart item count");
                                    app.setCartItemsCount(Integer.parseInt(value));
                                }
                            }
                        }
                    }
                    InputStream data = new ByteArrayInputStream(okResponse.body().string().getBytes(StandardCharsets.UTF_8));
                    Log.i(TAG, "okResponse code:" + okResponse.code());
                    returnResponse = new WebResourceResponse(mimeType,encoding,statusCode,reasonPhrase,responseHeaders,data);
                } else {
                    Log.w(TAG,"okResponse fail");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return returnResponse;
     }
Community
  • 1
  • 1
  • oh nice.... sounds like it will work I'll try it later today and if it works you will be rewarded :) PS the "Part #1" solution is how to make ajax calls from the app in the webview and to receive feedback when it starts and when it ends... the "Part #2" solution sounds like the right answer so you can post the quotes from the code to be complete answer thanks – Sir NIkolay Cesar The First Nov 09 '16 at 15:44
  • 1
    I almost made it to work so i give you the bounty because it will expire soon and once I complete the hole thing I will post the complete solution – Sir NIkolay Cesar The First Nov 10 '16 at 16:20