webview加载html的离线缓存

首先知道webview自带离线缓存功能:

         mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);   //设置 缓存模式

LOAD_CACHE_ONLY:  不使用网络,只读取本地缓存数据
LOAD_DEFAULT:  根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

// 开启 DOM storage API 功能 
         mWebView.getSettings().setDomStorageEnabled( true ); 
         //开启 database storage API 功能 
         mWebView.getSettings().setDatabaseEnabled( true );  
         String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; 
         //设置数据库缓存路径 
         mWebView.getSettings().setDatabasePath(cacheDirPath); 
         //设置  Application Caches 缓存目录 
         mWebView.getSettings().setAppCachePath(cacheDirPath); 
         //开启 Application Caches 功能 
         mWebView.getSettings().setAppCacheEnabled( true ); 
但是这都是通过直接加载一个URL来缓存的,而我的要求是加载本地的html,在html中有图片需要网络加载,html可以通过加网络请求后缓存到本地,但是其中的图片加载需要下载才能实现缓存的要求:

具体思路是通过得到HTML中的图片地址,然后下载,然后对webview更新,网上找到的资料是用js代码更新,但是测试的时候没有效果,所以我的思路是:

1.第一次加载时直接加载原html数据,其中的图片从网络加载;

2.将html代码中img标签替换为本地地址,并且将html代码缓存到本地,并且开始下载图片

3.再次读取该网页时首先判断本地是否有该网页的html代码,有的话读取本地已经替换过img标签的html代码;

4.由于图片已经下载在本地,加载该html代码时图片就从本地加载的,从而达到缓存的效果;

代码:

第一步:第一次加载时直接加载原html数据,其中的图片从网络加载,并且开始下载图片;

这是存储及读取html代码的部分,key为文件名,用URL,但是有//符号,最好用MD5进行编码,否则会报错

public static void saveHtml(String key, String value, Context ctx) {
    key = MD5Utils.encode(key);
    FileOutputStream fileOutputStream = null;
    BufferedWriter writer = null;
    try {
        fileOutputStream = ctx.openFileOutput(key, Context.MODE_APPEND);
        writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
        writer.write(value);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (writer != null) {
            try {
                writer.flush();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public static String getHtml(String key, Context ctx) {
    key = MD5Utils.encode(key);
    FileInputStream fileInputStream = null;
    BufferedReader reader = null;
    StringBuilder builder = null;
    try {
        fileInputStream = ctx.openFileInput(key);
        reader = new BufferedReader(new InputStreamReader(fileInputStream));
        builder = new StringBuilder();
        String line = "";
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    if (builder != null) {
        return builder.toString();
    }
    return null;
}

然后加载时先读取本地,如果没有该文件就读取网络数据:

final String url = GlobalContants.TEXT_URL;
responseHtml = CacheUtils.getHtml(url, getActivity());
httpUtils = new HttpUtils();
if (TextUtils.isEmpty(responseHtml)) {
    httpHandler = httpUtils.send(HttpRequest.HttpMethod.GET, url,
            new RequestCallBack<String>() {
                @Override
                public void onSuccess(ResponseInfo<String> responseInfo) {
                    responseHtml = responseInfo.result;
                }
                @Override
                public void onFailure(HttpException error, String msg) {
                }
            });
}
然后webview.loadDataWtihBaseURL对这段html加载就可以了。

第二步:将html代码中img标签替换为本地地址,并且将html代码缓存到本地,并且开始下载图片

将从网络加载的html代码的img标签进行替换,然后保存到本地:

public void changeHtml(String htmlString) {
    imgUrls.clear();
    doc = Jsoup.parse(htmlString);//将html字符串解析为Document
    if (doc == null) {
        return;
    }
    Elements es1 = doc.select("script");
    if (es1 != null) {
        es1.remove();
    }
    Elements es = doc.getElementsByTag("img");
    for (Element e : es) {
        String imgUrl = e.attr("src");
        imgUrls.add(imgUrl);//将图片的网络地址保存到list
        String imgName;
        int index = imgUrl.lastIndexOf("/");
        imgName = imgUrl.substring(index + 1, imgUrl.length());//通过URL截取到图片名
       	String filePath = "file:///" + Environment.getExternalStorageDirectory() + "/test/" + imgName;
        e.attr("src", filePath);//替换img标签的src属性内容
        
    }
    CacheUtils.saveHtml(key, doc.html(), context);//将替换img标签的html保存到本地
    downloadImg(imgUrls);//开始下载图片到本地
}
这里需要使用jsoup这个包,将html解析为Document,然后遍历img标签,将其中的URL保存到list中,然后替换为本地地址,注意地址前需要加
"file:///"

这样就可以在html代码中加载本地图片,在这里需要将这段更改后的html代码保存到本地,并开始下载:

这里我使用的是Xutils来进行下载,注意下载路径是上面标签替换的路径:

private void downloadImg(final List<String> imgUrls) {
    //若传入参数为空,则直接返回
    if (imgUrls.size() == 0)
        return;
    File dir = new File(Environment.getExternalStorageState() + "/anytime/");
    if (!dir.exists()) {
        dir.mkdir();
    }
    for (final String urlStr : imgUrls) {
        if (urlStr == null) {
            continue;
        }
        int index = urlStr.lastIndexOf("/");
        String fileName = urlStr.substring(index + 1, urlStr.length());
        File file = new File(Environment.getExternalStorageDirectory() + "/anytime/" + fileName);
        if (file.exists()) {
            continue;
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        HttpUtils http = new HttpUtils();
            /*1.下在文件的地址。2.保存至本地的文件路径。*/
        HttpHandler handler = http.download(urlStr, file.getPath(), false, false,
                new RequestCallBack<File>() {

                    @Override
                    public void onStart() {
                    }
                    @Override
                    public void onLoading(long total, long current,                                                            boolean isUploading) {
                    }
                    @Override
                    public void onSuccess(ResponseInfo<File> responseInfo) {
                    }
                    @Override
                    public void onFailure(HttpException error, String msg) {
                    }
                });
    }
}
需要将上面报错图片网络地址的list传入就可以,注意http.download的参数,第四个必须为false,如果为true的话可能会将图片的名字更改,我在做的过程中就遇到了这个问题。

第三步,第四部:再次读取时所有资源都来自本地


测试过程中还可以,但是想到一种情况,就是图片没有下载完毕,但是下次读取时因为是本地的html代码,其中的img标签已经被替换,所以本地没有,网络地址也没有,就会读取图片失败,所以我的思路就是讲图片网络地址保存在img标签的属性下,读取本地html时检验一下是否所有img标签下的图片都下载了,如果没有下载就将该标签下的src属性替换回网络地址,这样webview加载时本地有的图片就加载本地,本地没有则加载网络图片。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值