Android WebKit

这段时间基于项目需要 在开发中与WebView的接触比较多,前段时间关于HTML5规范尘埃落定的消息出现在各大IT社区头版上,更有人说:HTML5将颠覆原生App开发 虽然我不太认同这一点 但是关于HTML5+JS+CSS+Native的跨平台开发模式还是为很多企业节省了开发资源和成本、一定程度上提升了WebView的使用率和地位。


网上关于HTML5规范定稿的一篇见解文章:

http://www.csdn.net/article/2014-11-06/2822513-how-html5-changes


本篇主要基于这段时间对WebView的使用经验和网上学习到的对WebView开发做一个要点小结:


一、WebView基于webkit引擎展现web页面的控件,使用前需要在Android Manifest file中配置internet访问权限,否则提示页面无法访问。

?
1
2
3
4
<manifest ...="">
    <uses-permission android:name="android.permission.INTERNET">
    ...
</uses-permission></manifest>


二、WebView属性的设置
1、设置WebSettings类
WebSettings用来对WebView的配置进行配置和管理,比如是否可以进行文件操作、缓存的设置、页面是否支持放大和缩小、是否允许使用数据库api、字体及文字编码设置、是否允许js脚本运行、是否允许图片自动加载、是否允许数据及密码保存等等
示例代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
webSettings.setDomStorageEnabled(true); 
webSettings.setDatabaseEnabled(true);
webSettings.setAppCacheEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setSavePassword(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
 /**
  * 用WebView显示图片,可使用这个参数 设置网页布局类型:
  * 1、LayoutAlgorithm.NARROW_COLUMNS :适应内容大小
  * 2、LayoutAlgorithm.SINGLE_COLUMN : 适应屏幕,内容将自动缩放
  */
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSettings.setUseWideViewPort(true);
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mWebView.setHorizontalScrollbarOverlay(true);
mWebView.setHorizontalScrollBarEnabled(true);
mWebView.requestFocus();
2、设置WebChromeClient子类
WebChromeClient会在一些影响浏览器ui交互动作发生时被调用,比如WebView关闭和隐藏、页面加载进展、js确认框和警告框、js加载前、js操作超时、webView获得焦点等等

?
1
mWebView.setWebChromeClient(new MyWebChromeClient());
3、设置WebViewClient子类
WebViewClient会在一些影响内容渲染的动作发生时被调用,比如表单的错误提交需要重新提交、页面开始加载及加载完成、资源加载中、接收到https认证需要处理、页面键盘响应、页面中的url打开处理等等

?
1
mWebView.setWebViewClient(new MyWebViewClient());
4、设置addJavascriptInterface方法
使Js调用Native本地Java对象,实现本地Java代码和HTML页面进行交互,
注意:因为安全问题的考虑 Google在使用Android API 17以上的版本的时候 需要通过@JavascriptInterface来注解的Java函数才能被识别可以被Js调用。


三、设置当前网页的链接仍在WebView中跳转,而不是跳到手机浏览器里显示,
在WebViewClient的子类中重写shouldOverrideUrlLoading函数 代码如下:

?
1
2
3
4
5
6
7
8
webView.setWebViewClient(new WebViewClient() { 
   
    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
        view.loadUrl(url); 
        return true
    
});
shouldOverrideUrlLoading表示当前webView中的一个新url需要加载时,给当前应用程序一个处理机会,如果没有重写此函数,webView请求ActivityManage选择合适的方式处理请求,就像弹出uc和互联网让用户选择浏览器一样。重写后return true表示让当前程序处理,return false表示让当前webView处理

四、设置开始加载网页、加载完成、加载错误时处理
在WebViewClient子类中分别重写如下父类函数 代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
webView.setWebViewClient(new WebViewClient() { 
   
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        // 开始加载网页时处理 如:显示"加载提示" 的加载对话框
        DialogManager.showLoadingDialog(this);
    }
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        // 网页加载完成时处理  如:让 加载对话框 消失
        DialogManager.dismissLoadingDialog();
    }
    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        super.onReceivedError(view, errorCode, description, failingUrl);
        // 加载网页失败时处理  如:
        view.loadDataWithBaseURL(null,
                "<span style="\"color:#FF0000\"">网页加载失败</span>",
                "text/html",
                "utf-8",
                null);
    
});
五、处理https请求,为WebView处理ssl证书设置
WebView默认是不处理https请求的,页面显示空白,需要进行如下设置
在WebViewClient子类中重写父类的onReceivedSslError函数 代码如下:
?
1
2
3
4
5
6
7
8
9
webView.setWebViewClient(new WebViewClient() { 
   
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();  // 接受信任所有网站的证书
        // handler.cancel();   // 默认操作 不处理
        // handler.handleMessage(null);  // 可做其他处理
    }
});

六、显示页面加载进度
在WebChromeClient子类中重写父类的onProgressChanged函数 代码如下:
?
1
2
3
4
5
6
7
8
9
10
11
webView.setWebChromeClient(new WebChromeClient() { 
   
    public void onProgressChanged(WebView view, int progress) { 
        setTitle("页面加载中,请稍候..." + progress + "%"); 
        setProgress(progress * 100); 
   
        if (progress == 100) { 
            setTitle(R.string.app_name); 
        
    
});
onProgressChanged通知应用程序当前页面加载的进度
progress表示当前页面加载的进度,为1至100的整数

七、back键控制网页后退
Activity默认的back键处理为结束当前Activity,WebView查看了很多网页后,希望按back键返回上一次浏览的页面,这个时候我们就需要覆盖WebView所在Activity的onKeyDown函数,告诉他如何处理,代码如下:

?
1
2
3
4
5
6
7
public boolean onKeyDown(int keyCode, KeyEvent event) { 
    if (webView.canGoBack() && event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { 
        webView.goBack(); 
        return true
    
    return super.onKeyDown(keyCode, event); 
}
其中webView.canGoBack()在webView含有一个可后退的浏览记录时返回true
webView.goBack();表示返回至webView的上次访问页面

八、使用addJavascriptInterface完成和js交互
1、Js中调Native本地Java方法
设置webView的addJavascriptInterface方法,该方法有两个参数,第一个参数为被绑定到js中的类实例,第二个参数为在js中暴露的类别名,在js中引用java对象就是用这个名字
在Native Java代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
class JavaScriptInterface{
    Context mContext;
    /** Instantiate the interface and set the context */
    JavaScriptInterface(Context c) {
        mContext = c;
    }
    /** Show a toast from the web page
      * 由Js调用执行Native本地Java方法
      */
    @JavascriptInterface
    public void showToast(String toast) {
        Log.d("TAG", "Js Invoker Native Function");
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }      
         
}
在HTML中Js调用Native方法 代码如下:

?
1
2
3
4
5
6
7
<input type="button" value="Say hello" onclick="showAndroidToast('Hello Android!')">
<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>
2、Java调Js方法
比如在HTML中有如下Js函数

?
1
2
3
4
5
<script type="text/javascript">
      function showAlert() {
        alert("Be executed by Native");
    }
</script>
在Native调Js方法如下:

?
1
mWebView.loadUrl("javascript:showAlert()");

九、WebView缓存模式的设置
1、网页数据缓存
当使用WebView加载HTML网页时,会在我们data/应用package下生成database与cache两个文件夹:
我们请求的Url记录是保存在webviewCache.db里,而url的内容是保存在webviewCache文件夹下.

五种缓存模式的设置setCacheMode:
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,都使用缓存中的数据。

如示例代码:

?
1
2
3
4
5
6
WebSettings webSettings = mWebView.getSettings();
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);  //设置 缓存模式 
// 开启 DOM storage API 功能 
webSettings.setDomStorageEnabled(true); 
//开启 database storage API 功能 
webSettings.setDatabaseEnabled(true);

2、H5缓存
通过setAppCacheEnabled(boolean flag)设置H5的缓存是否打开,默认关闭。
根据setAppCachePath(String appCachePath)提供的路径,在H5使用缓存过程中生成的缓存文件。
通过setAppCacheMaxSize(long appCacheMaxSize)设置缓存最大容量。

如示例代码:

?
1
2
3
4
5
6
7
8
9
10
String cacheDirPath = getCacheDir().getAbsolutePath()+ "/webViewCache ";
WebSettings webSettings = mWebView.getSettings();
//开启 database storage API 功能 
webSettings.setDatabaseEnabled(true);   
//设置数据库缓存路径 
webSettings.setDatabasePath(cacheDirPath);
//开启Application H5 Caches 功能 
webSettings.setAppCacheEnabled(true);
//设置Application Caches 缓存目录 
webSettings.setAppCachePath(cacheDirPath);

十、加快HTML网页加载完成速度
默认情况html代码 下载 到WebView后,webkit开始解析网页各个节点,发现有外部样式文件或者外部脚本文件时,会异步发起网络请求下载文件,但如果在这之前也有解析到image节点,那势必也会发起网络请求下载相应的图片。在网络情况较差的情况下,过多的网络请求就会造成带宽紧张,影响到css或js文件加载完成的时间,造成页面空白loading过久。解决的方法就是告诉WebView先不要自动加载图片,等页面finish后再发起图片加载。
故在WebView初始化时设置如下代码:

?
1
2
3
4
5
6
7
public void int () {
    if(Build.VERSION.SDK_INT >= 19) {
        webView.getSettings().setLoadsImagesAutomatically(true);
    } else {
        webView.getSettings().setLoadsImagesAutomatically(false);
    }
}
同时在WebView的WebViewClient子类中重写onPageFinished()方法添加如下代码:

?
1
2
3
4
5
6
@Override
public void onPageFinished(WebView view, String url) {
    if(!webView.getSettings().getLoadsImagesAutomatically()) {
        webView.getSettings().setLoadsImagesAutomatically(true);
    }
}
从上面的代码,可以看出我们对系统API在19以上的版本作了兼容。因为4.4以上系统在onPageFinished时再恢复图片加载时,如果存在多张图片引用的是相同的src时,会只有一个image标签得到加载,因而对于这样的系统我们就先直接加载。


十一、WebView硬件加速导致页面渲染闪烁问题解决方法
关于Android硬件加速 开始于Android 3.0 (API level 11),在四个级别上开启/关闭硬件加速
1、Application级别:为整个应用程序开启硬件加速,在AndroidManifest中加入如下配置

?
1
</application>
2、Activity级别:控制每个activity是否开启硬件加速,只需在activity元素中添加android:hardwareAccelerated属性即可

?
1
</activity>
3、Window级别:注:目前还不支持在Window级别上关闭硬件加速

?
1
2
3
getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
4、View级别:运行时单个view硬件加速,目前Android还不支持在View级别开启硬件加速 代码如下:

?
1
mView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

[//TODO 关于Android硬件加速 小吕有时间会更详细的单独整理成一篇来做介绍 
先提供学习地址:http://android.toolib.net/guide/topics/graphics/hardware-accel.html ]

我们开启硬件加速后,WebView渲染页面更加快速,拖动也更加顺滑。但有个副作用就是容易会出现页面加载白块同时界面闪烁现象。解决这个问题的方法是设置WebView暂时关闭硬件加速 代码如下:

?
1
2
3
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

十二、其他注意事项:
1> 从网络上下载html页面的过程应放在工作线程(后台线程)中
2> html下载成功后渲染出html的步骤应放在UI主线程,不然WebView加载网页过程会容易报错

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jQuery的事件绑定和解绑

1、绑定事件 语法&#xff1a; bind(type,data,fn) 描述&#xff1a;为每一个匹配元素的特定事件&#xff08;像click&#xff09;绑定一个事件处理器函数。 参数解释&#xff1a; type (String) : 事件类型 data (Object) : (可选) 作为event.data属性值传递给事件对象的额外数…

软件测试框架课程考试_那考试准备课程值得吗?

软件测试框架课程考试By Levi Petty李维佩蒂(Levi Petty) This project uses a public, synthesized exam scores dataset from Kaggle to analyze average scores in Math, Reading, and Writing subject areas, relative to the student’s parents’ level of education an…

开博第一天

开博第一天 纪念一下 转载于:https://www.cnblogs.com/yang-9654/p/9959388.html

GitLab 11.9 正式发布,自动化工具 ChatOps 已开源

GitLab 11.9 已正式发布&#xff0c;该版本新增了两个和安全相关的特性&#xff0c;一是快速检查私密信息是否泄漏&#xff0c;从该版本起在 CI/CD 过程中会扫描开发者提交的信息是否包含私密内容&#xff0c;有的话会在合并 PR 时向开发者发送警报&#xff1b;二是改进了合并 …

DOCKER windows安装

DOCKER windows安装 DOCKER windows安装 1.下载程序包2. 设置环境变量3. 启动DOCKERT4. 分析start.sh5. 利用SSH工具管理6. 下载镜像 6.1 下载地址6.2 用FTP工具上传tar包6.3 安装6.4 查看镜像6.5 运行 windows必须是64位的 1.下载程序包 安装包 https://github.com/boot2doc…

为什么在Python代码中需要装饰器

Python is praised for its clarity and syntactic sugariness. In this article, I will teach you to use decorators in Python to make your code readable and clean.Python的清晰性和语法含糖度受到赞誉。 在本文中&#xff0c;我将教您在Python中使用装饰器&#xff0c;…

Elasticsearch Reference [6.7] » Modules » Network Settings

2019独角兽企业重金招聘Python工程师标准>>> Search Settings Node Network Settingsedit Elasticsearch binds to localhost only by default. This is sufficient for you to run a local development server (or even a development cluster, if you star…

【百度】大型网站的HTTPS实践(一)——HTTPS协议和原理

大型网站的HTTPS实践&#xff08;一&#xff09;——HTTPS协议和原理 原创 网络通信/物联网 作者&#xff1a;AIOps智能运维 时间&#xff1a;2018-11-09 15:07:39 349 0前言 百度于2015年上线了全站HTTPS的安全搜索&#xff0c;默认会将HTTP请求跳转成HTTPS。从今天开始&…

数据清理最终实现了自动化

苹果 | GOOGLE | 现货 | 其他 (APPLE | GOOGLE | SPOTIFY | OTHERS) Editor’s note: The Towards Data Science podcast’s “Climbing the Data Science Ladder” series is hosted by Jeremie Harris. Jeremie helps run a data science mentorship startup called Sharpest…

mui 与jquery 同时使用,$冲突解决办法。

(function($,doc,$$) { 。。。。。 }(mui, document, jQuery)); 使用$$代替jQuery。 var $$jQuery.noConflict();此方法也可以 转载于:https://www.cnblogs.com/mustanglqt/p/10608499.html

LVS原理介绍及安装过程

一、ARP技术概念介绍 为什么讲ARP技术&#xff0c;因为平常工作中有接触。还有就是LVS的dr模式是用到arp的技术和数据。 1、什么是ARP协议 ARP协议全程地址解析协议&#xff08;AddressResolution Protocol&#xff0c;ARP&#xff09;是在仅知道主机的IP地址时确定其物理地…

Python气流介绍

This is a memo to share what I have learnt in Apache Airflow, capturing the learning objectives as well as my personal notes. The course is taught by Mike Metzger from DataCamp.这是一份备忘录&#xff0c;旨在分享我在Apache Airflow中学到的知识&#xff0c;记录…

java~springcloud微服务目录索引

回到占占推荐博客索引 最近写了不过关于java&#xff0c;spring&#xff0c;微服务的相关文章&#xff0c;今天把它整理一下&#xff0c;方便大家学习与参考。 java~springcloud微服务~目录索引 springcloud~服务注册与发现Eureka的使用 springcloud~配置中心的使用 springclou…

DNS Bind9在windows7下

有些公司技术力量薄弱一些&#xff0c;一直在用windows系统&#xff0c;所以本文从windows出发&#xff0c;安装bind&#xff0c;利用它的view功能&#xff0c;做智能DNS&#xff0c;解决双线机房南北电信联通访问问题前言&#xff1a; 搞LINUX的朋友都知道&#xff0c;bind是l…

正确的词典访问方式

unity3d 词典访问Python字典指南 (Python Dictionary Guide) The dictionary is one of the data structures that are ready to use when programming in Python.字典是使用Python进行编程时可以使用的数据结构之一。 在我们开始之前&#xff0c;什么是字典&#xff1f; (Bef…

Vue.js(5)- 全局组件

全局组件 定义组件的语法 Vue.component(组件的名称, { 组件的配置对象 }) 在组件的配置对象中&#xff1a;可以使用 template 属性指定当前组件要渲染的模板结构&#xff1b; 使用组件的语法 把 组件的名称, 以标签的形式&#xff0c;引入到页面上就行&#xff1b; // 导入v…

DNS的几个基本概念:

一&#xff0e; 根域 就是所谓的“.”&#xff0c;其实我们的网址www.baidu.com在配置当中应该是www.baidu.com.&#xff08;最后有一点&#xff09;&#xff0c;一般我们在浏览器里输入时会省略后面的点&#xff0c;而这也已经成为了习惯。 根域服务器我们知道有13台&#xff…

废水处理计算书 excel_废水监测数据是匿名的吗?

废水处理计算书 excelOur collective flushes help track and respond to Covid-19 and so much more. Your body waste contains harvestable compounds that can reveal your illnesses and diseases, consumption habits, and cosmetic use. Researchers gain insights from…

文件在线预览 图片 PDF Excel Word

1、前端实现pdf文件在线预览功能 方式一、pdf文件理论上可以在浏览器直接打开预览但是需要打开新页面。在仅仅是预览pdf文件且UI要求不高的情况下可以直接通过a标签href属性实现预览 <a href"文档地址"></a> 2、word、xls、ppt文件在线预览功能 word、pp…

数据科学还是计算机科学_您应该拥有数据科学博客的3个原因

数据科学还是计算机科学“Start a Blog to cement the things you learn. When you teach what you’ve learned in the form of a blog you can see the gaps in your knowledge and fill them in” — My Manager (2019)“创建一个博客以巩固您所学到的东西。 当您以博客的形…