CacheWebView
简介:Custom implement Android WebView cache, offline website, let cahe config more simple and flexible
标签:
CacheWebView 通过拦截资源实现自定义缓存静态资源。突破 WebView 缓存空间限制,让缓存更简单。让网站离线也能正常访问。
为什么要用 CacheWebView
- 让 WebView 缓存空间更大
- 强制缓存静态资源,这样会更快
- 想方便的拿到 web 缓存资源,比如说从缓存中拿页面已经加载过的图片
使用方式
引入库
注意 2.x.x 不兼容 1.x.x
compile 'ren.yale.android:cachewebviewlib:2.1.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 .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.**{*;}