[go: nahoru, domu]

Skip to content

Custom implement Android WebView cache, offline website, let cahe config more simple and flexible

License

Notifications You must be signed in to change notification settings

commonmac/CacheWebView

 
 

Repository files navigation

CacheWebView

English

CacheWebView通过拦截资源实现自定义缓存静态资源。突破WebView缓存空间限制,让缓存更简单。让网站离线也能正常访问。

为什么要用CacheWebView

  • 让WebView缓存空间更大
  • 强制缓存静态资源,这样会更快
  • 想方便的拿到web缓存资源,比如说从缓存中拿页面已经加载过的图片

使用方式

引入库

注意2.x.x 不兼容 1.x.x

implementation 'ren.yale.android:cachewebviewlib:2.2.1'

修改代码

Application 里初始化


    WebViewCacheInterceptorInst.getInstance().
                init(new WebViewCacheInterceptor.Builder(this));

给WebView添加拦截

  • 如果你的项目minSdkVersion>=21
    mWebView.setWebViewClient(new WebViewClient(){

            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Nullable
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                return  WebViewCacheInterceptorInst.getInstance().interceptRequest(request);
            }

            @Nullable
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                return  WebViewCacheInterceptorInst.getInstance().interceptRequest(url);
            }
     });

  • 如果你的项目minSdkVersion<21

将调用 mWebView.loadUrl(url) 的地方替换为:WebViewCacheInterceptorInst.getInstance().loadUrl(mWebView,url)


    mWebView.setWebViewClient(new WebViewClient(){


            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                WebViewCacheInterceptorInst.getInstance().loadUrl(mWebView,request.getUrl().toString());
                return true;
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                WebViewCacheInterceptorInst.getInstance().loadUrl(mWebView,url);
                return true;
            }

            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Nullable
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                return  WebViewCacheInterceptorInst.getInstance().interceptRequest(request);
            }

            @Nullable
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                return  WebViewCacheInterceptorInst.getInstance().interceptRequest(url);
            }
    });

以上就配置完毕,其他代码不用改,这样拥有默认100M缓存空间;如果你需要更详细的配置,可以看看下面的进阶设置;


  • 腾讯X5内核WebView兼容处理
     mWebView.setWebViewClient(new WebViewClient() {

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView webView, String s) {
                return WebResourceResponseAdapter.adapter(WebViewCacheInterceptorInst.getInstance().
                        interceptRequest(s));
            }

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest) {

                return WebResourceResponseAdapter.adapter(WebViewCacheInterceptorInst.getInstance().
                        interceptRequest(WebResourceRequestAdapter.adapter(webResourceRequest)));
            }
        });

下面是兼容代码,可以参考:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class WebResourceRequestAdapter implements android.webkit.WebResourceRequest {

    private com.tencent.smtt.export.external.interfaces.WebResourceRequest mWebResourceRequest;

    private WebResourceRequestAdapter(com.tencent.smtt.export.external.interfaces.WebResourceRequest x5Request){
        mWebResourceRequest = x5Request;
    }

    public static WebResourceRequestAdapter adapter(com.tencent.smtt.export.external.interfaces.WebResourceRequest x5Request){
        return new WebResourceRequestAdapter(x5Request);
    }

    @Override
    public Uri getUrl() {
        return mWebResourceRequest.getUrl();
    }

    @Override
    public boolean isForMainFrame() {
        return mWebResourceRequest.isForMainFrame();
    }

    @Override
    public boolean isRedirect() {
        return mWebResourceRequest.isRedirect();
    }

    @Override
    public boolean hasGesture() {
        return mWebResourceRequest.hasGesture();
    }

    @Override
    public String getMethod() {
        return mWebResourceRequest.getMethod();
    }

    @Override
    public Map<String, String> getRequestHeaders() {
        return mWebResourceRequest.getRequestHeaders();
    }
}

public class WebResourceResponseAdapter extends com.tencent.smtt.export.external.interfaces.WebResourceResponse {

    private android.webkit.WebResourceResponse mWebResourceResponse;

    private WebResourceResponseAdapter(android.webkit.WebResourceResponse webResourceResponse){
        mWebResourceResponse = webResourceResponse;
    }

    public static WebResourceResponseAdapter adapter(android.webkit.WebResourceResponse webResourceResponse){
        if (webResourceResponse == null){
            return null;
        }
        return new WebResourceResponseAdapter(webResourceResponse);

    }

    @Override
    public String getMimeType() {
        return mWebResourceResponse.getMimeType();
    }

    @Override
    public InputStream getData() {
        return mWebResourceResponse.getData();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public int getStatusCode() {
        return mWebResourceResponse.getStatusCode();
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public Map<String, String> getResponseHeaders() {
        return mWebResourceResponse.getResponseHeaders();
    }

    @Override
    public String getEncoding() {
        return mWebResourceResponse.getEncoding();
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public String getReasonPhrase() {
        return mWebResourceResponse.getReasonPhrase();
    }
}


如果你的项目minSdkVersion<21, 在 mWebView.loadUrl(url) 之后调用 WebViewCacheInterceptorInst.getInstance().loadUrl(url,mWebView.getSettings().getUserAgentString());


进阶设置

  • 基本设置
   WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);

    builder.setCachePath(new File(this.getCacheDir(),"cache_path_name"))//设置缓存路径,默认getCacheDir,名称CacheWebViewCache
                       .setDynamicCachePath(new File(this.getCacheDir(),"dynamic_webview_cache"))
                       .setCacheSize(1024*1024*100)//设置缓存大小,默认100M
                       .setConnectTimeoutSecond(20)//设置http请求链接超时,默认20秒
                       .setReadTimeoutSecond(20)//设置http请求链接读取超时,默认20秒
                       .setCacheType(CacheType.NORMAL);//设置缓存为正常模式,默认模式为强制缓存静态资源

    WebViewCacheInterceptorInst.getInstance().init(builder);
  • 设置缓存后缀

CacheWebview通过后缀判断来缓存静态文件,可以添加删除

    WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);

    CacheExtensionConfig extension = new CacheExtensionConfig();
    extension.addExtension("json").removeExtension("swf");//添加删除缓存后缀

    builder.setCacheExtensionConfig(extension);

    WebViewCacheInterceptorInst.getInstance().init(builder);

默认有以下后缀缓存

    private static HashSet STATIC = new HashSet() {
        {
            add("html");
            add("htm");
            add("js");
            add("ico");
            add("css");
            add("png");
            add("jpg");
            add("jpeg");
            add("gif");
            add("bmp");
            add("ttf");
            add("woff");
            add("woff2");
            add("otf");
            add("eot");
            add("svg");
            add("xml");
            add("swf");
            add("txt");
            add("text");
            add("conf");
            add("webp");
        }
    };

默认有以下后缀不缓存

    private static HashSet NO_CACH = new HashSet() {
        {
            add("mp4");
            add("mp3");
            add("ogg");
            add("avi");
            add("wmv");
            add("flv");
            add("rmvb");
            add("3gp");
        }
    };
  • 设置Assets路径

CacheWebview可以从Assets路径加载静态资源,只要设置了Assets路径就是开启此功能,默认未开启;


  
    WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);
    //默认精确匹配地址规则
    builder.setAssetsDir("static");
    
    //后缀匹配规则
    //builder.isAssetsSuffixMod(true);
    //WebViewCacheInterceptorInst.getInstance().initAssetsData(); //后台线程获取Assets文件资源
    
    WebViewCacheInterceptorInst.getInstance().init(builder);

builder.setAssetsDir("static")后匹配规则:

assets 结构如下:

(1)默认精确匹配规则:那么只有满足这种结构的url:http://xxx.com/scripts/jquery.min.js 都会从assets获取资源

(2)后缀匹配规则:那么只要满足这种结构的url:http://xxx.com/x/xx/scripts/jquery.min.js 都会从assets获取资源

  • 自定义拦截规则
    builder.setResourceInterceptor(new ResourceInterceptor() {
            @Override
            public boolean interceptor(String url) {
                return true;//按照默认规则,false 不拦截资源
            }
        });
  • 获取缓存文件

    String url = "http://m.mm131.com/css/at.js";
    InputStream inputStream =  WebViewCacheInterceptorInst.getInstance().getCacheFile(url);
    if (inputStream!=null){

    }

  • 清除缓存文件
    WebViewCacheInterceptorInst.getInstance().clearCache();
  • 强制缓存失效

    强制缓存失效后,由WebView正常加载资源

    WebViewCacheInterceptorInst.getInstance().enableForce(false);
  • HostnameVerifier设置

builder.setTrustAllHostname();不安全

    WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);
    builder.setTrustAllHostname();//HostnameVerifier不验证,HostnameVerifier.verify()返回true,默认正常验证
    WebViewCacheInterceptorInst.getInstance().init(builder);

  • SSLSocketFactory 设置
    WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);
    builder.setSSLSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager);//自定义SSLSocketFactory和X509TrustManager
    WebViewCacheInterceptorInst.getInstance().init(builder);

  • Debug log

默认开启debug log , TAG="CacheWebView",可以关闭log

    WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);
    builder.setDebug(false);
    WebViewCacheInterceptorInst.getInstance().init(builder);

  • 非单例模式

调用方法和单例一样

    WebViewCacheInterceptor.Builder builder =  new WebViewCacheInterceptor.Builder(this);
    WebViewRequestInterceptor webViewRequestInterceptor = builder.build();
    webViewRequestInterceptor.getCacheFile("");

混淆

#CacheWebview
-dontwarn ren.yale.android.cachewebviewlib.**
-keep class ren.yale.android.cachewebviewlib.**{*;}

#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}

#okio
-dontwarn okio.**
-keep class okio.**{*;}

贡献

如何贡献代码

博客

如何让Android WebView访问更快

About

Custom implement Android WebView cache, offline website, let cahe config more simple and flexible

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%