android webview webp,在WebView中使用webp格式图片
很早之前,我们的项目中就已经采用了webp格式,但是由于webView本身并不能解析webp格式,所以我们基于webView的文章详情页就无法使用到这项优化。
那么有没有什么办法能实现呢?当然是有的。
在开始技术讲解之前需要先说明,本文的技术方案,是基于本项目的情况:文章的正文大部分通过接口直接获取到,通过在客户端本地进行html正文组装,最后通过webView的loadHTMLString方法进行加载显示。普通的图片可以通过转换链接得到webp服务器获取到相应的webp版的图片。
本项目中,图片缓存使用了SDWebImage,并且开启了webp支持功能,那么我们对详情页webView的处理也会基于此来实现。
通过思考,方案其实还是比较明确的,就是替换html中图片链接,通过客户端下载webp图片,然后在通过js刷新出页面上的下完的图片,但实际开发中也遇到了一些坑,比如:
HTML解析库的setAttributeNamed不能增加属性
webp服务器图片下载后的默认缓存时gif不能正常存储
下载完的图片不能实时通过js更改src为本地文件地址加载出来
最终的技术实现:
1.对下载回来的html内容进行处理,获取所有图片链接,并进行webp链接处理转换
对html内容的解析处理我使用的是Objective-C-HMTL-Parser,但是该库已经多年不维护,这里有我fork后进行部分优化调整的版本:https://github.com/YueRuo/Objective-C-HMTL-Parser
处理html图片核心处理逻辑代码:
@try {
HTMLParser *parser = [[HTMLParser alloc] initWithString:htmlContent error:&error];
HTMLNode *bodyNode = [parser body];
if (error) {
return;
}
//得到所有的img标签
NSArray *inputNodes = [bodyNode findChildTags:@"img"];
for (HTMLNode *inputNode in inputNodes) {
NSString *imageSrc = [inputNode getAttributeNamed:@"src"];
if (!imageSrc) {
continue;
}
NSString *newSrc = [[GlobalVariable shareInstance] resizeWebpImageWithUrl:imageSrc size:CGSizeMake((SCREEN_WIDTH - 20) * 2, 0)];//根据原图片,得到webp服务器使用的图片链接,需要有webp处理服务器
//检查本地图片缓存
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:[NSURL URLWithString:newSrc]];
NSString *localPath = [[SDImageCache sharedImageCache] defaultCachePathForKey:key];
NSString *webpImage = newSrc;
BOOL localExsit = [[NSFileManager defaultManager] fileExistsAtPath:localPath];
if (localExsit) {
newSrc = [NSString stringWithFormat:@"file://%@", localPath];
}
//存储疑似webp图片和原图片,如果newSrc和webp相同则说明本地没有缓存图片
[_webpImageUrlDic setObject:webpImage forKey:newSrc];
if(localExsit){
setAttributeNamed(inputNode->_node, "src", [newSrc cStringUsingEncoding:NSUTF8StringEncoding]);
}else{
setAttributeNamed(inputNode->_node, "src", "详情页占位图@2x.png");
}
//给img标签中增加一个叫osrc的属性,便于后续处理
setAttributeNamed(inputNode->_node, "osrc", [newSrc cStringUsingEncoding:NSUTF8StringEncoding]);
}
htmlContent = [NSMutableString stringWithString:parser.doc.rawContents];
}
@catch (NSException *exception) {
}
@finally {
[webView loadHTMLString:htmlContent baseURL:baseUrl];
}
2.用原生方法下载webp图片,缓存到本地
下载之后会存储为jpg或png格式,这样就可以被webView进行本地加载,但是需要注意gif的存储特殊处理。
另外通过实验,直接通过js无法实时更新下载到本地的图片,只好通过图片的base64encode数据加载方式实现。
具体代码如下:
- (void)webViewDidFinishLoad:(UIWebView *)web {
//处理webp格式加载
[_webpImageUrlDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if([obj isEqualToString:key]){//说明这图没有缓存,还需要下载
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:obj] options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
if (image&&finished) {
NSString *js;
NSRange range = [[obj lowercaseString] rangeOfString:@".gif"];//检查是否是gif
BOOL isGif = (range.location != NSNotFound);
if (!isGif) {
[[SDImageCache sharedImageCache] storeImage:image forKey:obj];
NSString *base64 = [UIImageJPEGRepresentation(image,1) base64EncodedStringWithOptions:0];
js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/jpeg;base64,%@')",key,base64];
}else{//gif的图片如果直接存储,会变成jpg从而失去动画,因此要特殊处理
[[SDImageCache sharedImageCache] storeImage:image recalculateFromImage:false imageData:data forKey:key toDisk:true];
NSString *base64 = [data base64EncodedStringWithOptions:0];
js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/gif;base64,%@')",key,base64];
}
[NSThread excuteInMainThread:^{
[webView stringByEvaluatingJavaScriptFromString:js];
} async:false];
}
}];
} else {//缓存中存在,那么直接加载吧
NSString *js;
NSRange range = [[obj lowercaseString] rangeOfString:@".gif"];//检查是否是gif
NSData* data = [NSData dataWithContentsOfFile:[key stringByReplacingOccurrencesOfString:@"file://" withString:@""]];
NSString *base64 = [data base64EncodedStringWithOptions:0];
BOOL isGif = (range.location != NSNotFound);
if (!isGif) {
js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/jpeg;base64,%@')",obj,base64];
}else{
js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/gif;base64,%@')",obj,base64];
}
[NSThread excuteInMainThread:^{
[webView stringByEvaluatingJavaScriptFromString:js];
} async:false];
}
}];
}
3.回调webView页面,用本地链接替换原有的图片
加载已下载好的图片,这里主要通过js来实现,即第2步中的replaceWebPImg方法,该js方法可通过提前置于html的模板中,或者webViewDidFinishLoad后采用js注入进去
replaceWebPImg = function(src, localPath) {
var imgs = document.querySelectorAll('img[osrc="'+src+'"]'),len = imgs.length;;
for (var i = 0; i < len; i++) { var img = imgs[i]; img.src = localPath; }
}
好再次总结一下整个流程:
对服务器返回的htmlContent数据进行相应处理,检查图片是否存在缓存,存在则使用本地地址为src,不存在则把图片的src替换成占位图。记录下图片地址,并增加属性做好标记。
图片的地址进行webp转换,通过客户端进行下载
下载后的图片,通过js方法进行src更改,并且赋值的base64的图片编码数据,因为给本地地址无法实时展示出来
这篇写的比较简单,更详细的步骤请查阅上面的代码,里面我加上还算详细的注释,希望对想要在webView中使用webp图片的大家有所帮助。
android webview webp,在WebView中使用webp格式图片相关推荐
- Android Studio中关于9-patch格式图片的编译错误
最近在编译Android Studio开发的项目中在使用了9宫图后出现了编译错误,尝试了多种方法未能解决,最后仔细查看出错的日志发现,居然是图片的原因,图片中包含有alpah通道所以在执行app:me ...
- android 手势放缩_Android应用中实现手势控制图片缩放的完全攻略
一.概述现在app中,图片预览功能肯定是少不了的,用户基本已经形成条件反射,看到小图,点击看大图,看到大图两个手指开始进行放大,放大后,开始移动到指定部位~~~ 我相信看图的整个步骤,大家或者说用户应 ...
- VB中使用PNG格式图片的一种新方法
由于VB中的Image控件和Picture控件都不能直接加载PNG格式图片,给我们使用或浏览PNG格式的图片带来了困难.现行的解决方法主要是以下两种: (1)利用GDI显示PNG图片: (2)将PNG ...
- android 9格式吗,Android Studio中关于9-patch格式图片的编译错误
C#基础知识回顾-- 反射(3) C#基础知识回顾-- 反射(3) 获取Type对象的构造函数: 前一篇因为篇幅问题因为篇幅太短被移除首页,反射这一块还有一篇"怎样在程序集中使用反射&q ...
- 在MFC中显示Jpg格式图片的简单实现方法
在做的时候在网上找了很多这方面的资料,但实现方法都很烦,最近发现了一个很简单的实现方法,,与大家分享一下--思路主要还是利用MS的IPicture类完成. 1. 在窗口类中添加IPicture指针-- ...
- word中插入矢量格式图片
学术论文和报告中的图片质量直接影响可读性.质量差的插图可能直接引起审稿人的反感,甚至直接拒稿. 而图片清晰度是图片质量评估非常重要的指标. 在此推荐使用svg格式的文件,svg是可缩放矢量图形,文件大 ...
- android webview webp,iOS WebView中使用webp格式图片的方法
webp格式图片 webp格式图片是google推出的,相比jpg png有着巨大的优势,同样质量的图片webp格式的图片占用空间更小,在像电商这样图片比较多的App中,使用webp格式图片会很有优势 ...
- android 调用java类_Android中在WebView里实现Javascript调用Java类的方法
搜索热词 为了方便网页和Android应用的交互,Android系统提供了WebView中JavaScript网页脚本调用Java类方法的机制.只要调用addJavascriptInterface方法 ...
- 【Android 安装包优化】WebP 图片格式兼容与性能 ( Android 中的 WebP 图片格式兼容问题 | Android 中的 WebP 图片格式性能 )
文章目录 一.Android 中的 WebP 图片格式兼容问题 二.Android 中的 WebP 图片格式性能 三.参考资料 一.Android 中的 WebP 图片格式兼容问题 在 Android ...
最新文章
- OpenCV Mat矩阵(图像Mat)初始化及访问方法
- 四 Vue学习 router学习
- c语言错误的等式,C语言学习中几个常见典型错误分析.docx
- 开发日记-20190514 关键词 汇编语言(七)
- vue 使用fs_node.js中常用的fs文件系统
- 前端开发技术-剖析JavaScript单线程
- LiveVideoStack线上交流分享 ( 三 ) —— 实时视频通信质量评价及寻找视频质量甜点的方法...
- Java爬虫搜索原理实现
- 同步和异步概念(由DZW前端框架引发的百度地图api无法加载问题总结)
- java图片处理开源项目_如何处理离开开源项目
- 人工智能——数据、信息与知识
- 浏览器Quirksmode(怪异模式)与CSScompat
- 解决Mac系统finder卡顿转菊花的问题
- oracle建表多个主键怎么办,Oracle建表、索引、主键
- 如何创建一个简易的HTML网页框架
- 资产证券化:国际借鉴与中国实践案例 读后感
- 自成一派的风格楷体字体
- 年度绩效考核演示PPT模板
- 视频直播应用的竞争分析
- JMeter脚本录制步骤
热门文章
- HTML5期末大作业:电影在线观看网站设计——电影售票平台(8页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码
- 为新机让路走降价路线的两部手机,市场竞争太激烈,旗舰机也扛不住
- java学习之CookiSession
- 计算机应用笔试题及答案,计算机应用基础笔试试题及答案
- 【Baidu Apollo】控制
- 饼图、柱形图、堆积柱、折线图、散点图,到底应该怎么选?
- WebRTC 混音分析
- 最通俗易懂的p value讲解
- 鸟欲高飞先振翅,人求上进先读书
- 国内跨云端平台应用的大数据平台供应商,基于Hadoop的互联网大数据平台解决方案,武汉数道云...