Back

android - 重磅:实现了对于js/css/png等文件的缓存. 只要能拦截,就可以缓存!

发布时间: 2017-08-13 11:20:00

啥也不说了,直接上代码.核心方法是:  queryFromCacheIfPossible (代码不完整,仅仅是个描述作用. TODO: 公开成 github项目)

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            Log.d(TAG, "onPageStarted, 触发的url是====" + url);
            super.onPageStarted(view, url, favicon);
        }

        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            Log.d(TAG, "shouldInterceptRequest, 触发的url是====" + url);
            if(url.contains("__webpack_hmr")) {
                Log.d(TAG, "return empty response on __webpack_hmr");
                return new WebResourceResponse(null,null, null);
            }

            if( shouldQueryFromCache(url)) {
                return queryFromCacheIfPossible(url);
            }

            return super.shouldInterceptRequest(view, url);
        }



        public boolean shouldQueryFromCache(String url) {

            // endsWith 方法貌似不支持   a | b 这样的表达式...只好这么写了 ...   Orz
            boolean result =  url.endsWith("png") ||
                    url.endsWith("PNG") ||
                    url.endsWith("jpg") ||
                    url.endsWith("JPG") ||
                    url.endsWith("jpeg") ||
                    url.endsWith("JPEG") ||
                    url.endsWith("css") ||
                    url.endsWith("css.map") ||
                    url.endsWith("js") ||
                    url.endsWith("js.map");

            return result;
        }

        /**
         * 核心方法. 根据url, 向远程发起请求, 并保存文件到本地.
         */
        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        public WebResourceResponse queryFromCacheIfPossible(final String url) {
            Log.d(TAG, "== in queryFromCacheIfPossible, url: "+ url);

            String webResourceLocalFileName = getWebResourceLocalFileName(url);
            File webResourceCacheFile = new File( getContext().getCacheDir(), webResourceLocalFileName);

            if(webResourceCacheFile.exists()){
                Log.d(TAG, "== hit the cache: " + webResourceLocalFileName);
                try{
                    FileInputStream fileInputStream = new FileInputStream(new File(getContext().getCacheDir(), webResourceLocalFileName));
                    return new WebResourceResponse(getMimeTypeBySuffix(url), "utf-8", fileInputStream);
                }catch (IOException e){
                    e.printStackTrace();
                    return new WebResourceResponse(getMimeTypeBySuffix(url), "utf-8", null);
                }
            }else{
                Log.d(TAG, "== NOT hit the cache: " + webResourceLocalFileName);
                OkHttpClient okHttpClient = new OkHttpClient();
                Request request = new Request.Builder()
                        .url(url)
                        .build();
                try {
                    Response response = okHttpClient.newCall(request).execute();

                    writeHttpResponseToFile(url, response);
                    Log.d(TAG, "== mime : " + getMimeTypeBySuffix(url));
                    // 这段代码可以让图片正常显示!
                    //   js:  doing...
                    FileInputStream fileInputStream = new FileInputStream(new File(getContext().getCacheDir(), webResourceLocalFileName));

                    return new WebResourceResponse(getMimeTypeBySuffix(url), "utf-8", fileInputStream);

                }catch (IOException e){
                    Log.e(TAG, "== got IOException");
                    e.printStackTrace();
                    return new WebResourceResponse(getMimeTypeBySuffix(url), "utf-8", null);
                }
            }

        }

        public String getWebResourceLocalFileName(String url){
            String[] temp = url.split("/");
            String fileName = temp[temp.length - 1];
            return fileName;
        }

        public String writeHttpResponseToFile(String url, Response response){
            String fileName = getWebResourceLocalFileName(url);
            Log.d(TAG, "== in writeHttpResponseToFile");
            // TODO Write file ...
            File file = new File(getContext().getCacheDir(), fileName);

            try{
                BufferedSink bufferedSink = Okio.buffer(Okio.sink(file));
                bufferedSink.writeAll(response.body().source());
                bufferedSink.close();
            }catch(Exception e){
                Log.e(TAG, "== got error in writeHttpResponseToFile");
                e.printStackTrace();
            }
            return fileName;

        }

        public String getMimeTypeBySuffix(String url){
            String result = "";
            if(url.endsWith("png") || url.endsWith("PNG")){
                result = "image/png";
            }else if (url.endsWith("jpg") || url.endsWith("JPG")
                || url.endsWith("jpeg") || url.endsWith("JPEG")){
                result = "image/jpg";
            }else if (url.endsWith("css") || url.endsWith("css.map")){
                result = "text/css";
            }else if (url.endsWith("js") ||url.endsWith(".js.map") ){
                result = "application/javascript";
            }else{
                result = "text/plain";
            }
            return result;
        }

Back