首页 > 代码库 > [WebView学习之四]:迁移到Android4.4版本的WebView
[WebView学习之四]:迁移到Android4.4版本的WebView
上一篇我们学习了([WebView学习之三]:使用WebView来创建Apps),今天我们来继续学习。
(博客地址:http://blog.csdn.net/developer_jiangqq),转载请注明。
Author:hmjiangqq
Email:jiangqqlmj@163.com
Android4.4(API版本19)提供了一个基于Chromium版本的新版本WebView。该变化提高了WebView的性能,并且和最新的Web浏览器支持最新的HTML5,CSS3样式以及Javascript标准。当在Android4.4或者更高的版本上面运行时,任何使用WebView的application会继承使用这些特性。本文章主要描述了一下WebView的新特性。如果你设置targetSdkVersion为19或者更高时,那你就需要特别的注意。
[注]:当你设置targetSdkVersion为18或者更低的时候,WebView会运行"quirks mode"来避免下面一些问题的发生(当优化提高App性能以及更新Web标准)。特别是 single and narrow column layouts(单行栅栏布局)和defalut zoom levels(默认缩放比例)在Android4.4中不支持,可能还会存在其他一些不确定的差异。所以如果你设置targetSdkVersion版本为18或者更低的时候,一定要把应用程序在Android4.4或者更高的版本中进行测试。
你可以通过设置setWebContentsDebuggingEnabled()来在Chrome桌面上面进行远程调试,这样当我们迁移app到Android4.4版本WebView中,可以帮助解决一些出现的问题。WebView这个新特性可以帮助我们检查和分析Web内容,脚本以及网络活动。有关调试的更多请查看下一篇文章《Android的远程调试》
(一):用户代理更改(UseerAgent Changes)
如果你的WebView内容是基于用户代理的,你应该发现用户代码的内容已经发生了轻微的变化,现在的版本已经包含了Chrome版本:
Mozilla/5.0(Linux; Android 4.4; Nexus 4 Build/KRT16H) AppleWebKit/537.36
(KHTML,like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
如果你需要检索查询用户代理,但是不需要存储或者不想要实例化WebView,那么你应该使用静态方法,getDefaultUserAgent()。 但是如果你需要修改WebView的用户代理,那么你应该去使用getUserAgentString()方法。
(二):多线程和线程阻塞(Multi-threadingand Thread Blocking)
如果你在其他线程调用WebView中的方法,而不是App的UI线程,这个可能出现一些意想不到的错误。如果你的App使用多线程,你可以使用runOnUiThread()方法来确定确定你的代码在UI线程中执行。
<span style="font-size:18px;">runOnUiThread(new Runnable() { @Override public void run() { // Code for WebView goes here } }); </span>
同时我们应该确保永远不要阻塞UI线程,有时候当我们在等待javascript回调的时候,有些App会发生这个错误。例如:不要写如下的代码.
<span style="font-size:18px;">// This code is BAD and will block the UI thread webView.loadUrl("javascript:fn()"); while(result == null) { Thread.sleep(100); }</span>
你可以使用evaluateJavascript()来进行异步运行Javascript.
(三):自定义URL处理(Custom URL Handing)
当我们请求资源以及处理自定义URL结构链接的时候,新的WebView也提供额外的限制。例如:如果我们实现shouldOverrideUrlLoading()以及shouldInterceptRequest()这些回调方法,这样可以保证WebView只会回调合法的URLs。如果你横在使用一个自定义URL结构或者基于URL,有时候在Android4.4中接收加载数据失败。就要确保URL符合RFC 3986编码。
例如:下面的例子新版本的WebView可能不会调用shouldOverrideUrlLoading()方法。用户点击以下这些链接的时候情况可能会不同:
1.如果你通过使用一个不合法或者空的URL来调用loadData()或者loadDataWithBaseURL(),此时页面上面的链接类型可能不会回调shouldOverrideUrlLoading()方法。
[注]:如果你使用loadDataWithBaseURL(),其中base URL不合法或者为空时,所有的链接地址都需要为绝对地址。
2.如果你通过调用loadUrl()或者提供一个合法的base URL来调用loadDataBaseURL()加载页面。那么此时对该该页面地址回调shouldOverrideUrlLoading()方法,但是你收到是绝对地址。例如:这边你讲获取到"http://www.example.com/showProfile"而不仅仅是"showProfile"。
除了上面使用的那种链接地址类型,你还可以使用如下的那种自定义类型的URL:
<span style="font-size:18px;"><a href=http://www.mamicode.com/"example-app:showProfile">Show Profile>你可以在shouldOverrideUrlLoading()方法中进行处理这个URL:
<span style="font-size:18px;">// The URL scheme should be non-hierarchical (no trailing slashes) private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = http://www.mamicode.com/URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8");>如果你不能改变HTML,那么你可以调用loadDataWithBaseURL()并且设置一个base URL。通过自定义类型和一个合法的主机名进行组成.例如:
"example-app://<valid_host_name>"。例如:
<span style="font-size:18px;">webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA, null, "UTF-8", null); </span>该主机名(host name)应该符合RFC3986规范,并且最重要的是该以斜杠结尾。否则任何加载页面的请求都会意外终止。
(四)视图改变(ViewPortChanges)
1.视图窗体目标屏幕密度不在支持(Viewprot target-desitydpi no longersupported)
之前WebView支持指定“target-desitydpi”属性让网页设置指定的屏幕密度。现在该属性已经不在支持了,现在你应该图片资源以及CSS样式来进行解决。
2.当小屏幕的时候视图窗体自动缩放(Viewport zoomsin when small)
之前如果你的viewport宽度的值小于或等于320,这将设置为成"device-width",如果viewport的高度的值小于或等于WebView的高度.这将设置为"device-height"。现在当我们运行新的WebView的时候,WebView的宽和高会自动缩放来充满整个屏幕。
3 .多视图窗体标签不在支持(Multiple vieport tags not supported)
以前在一个Web页面上面如果包含多个viewport标签,WebView将会合并这些属性标签。在新的WebView中,只会使用最后的viewport标签,其他都会被忽略。
4.默认缩放被弃用(Default zoom is deprecated)
在界面 getDefaultZoom()和setDefaultZoom()来进行设置和获取页面缩放比例的方法将不会在支持。你应该在Web页面上面定义合适的viewport。
[注]:在Android4.4或者更高的版本中这些APIs将不会被支持,即时你的targetSdkVersion设置成18或者更低,也不会起作用了。
如果定义HTML的viewport属性的有关信息请想看:Pixel-PerfectUI in the WebView.
如果你不能设置HTML的视图窗体的宽度,你应该调用setUserWideViewPort()以确保页面能够合适的显示。例如:
<span style="font-size:18px;">WebSettings settings = webView.getSettings(); settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); </span>
五)样式风格变化(Styling Changes)
1.The backgroundCSS shorthand overrides background-size
2.使用CSS样式中的像素而不是屏幕像素大小(Sizes are in CSS pixels instead ofscreen pixels)
之前例如window.outerWidth和window.outerHeighet返回宽高属性是屏幕像素大小值。在新的WebView中,该返回是CSS样式中定义的像素值大小。
通常糟糕的设计就是尝试和计算物理尺寸大小。然而如果你设置原始缩放值为1.0并且禁止缩放,然后你可以使用window.devicePixelRatio获取缩放比例,然后乘以CSS定义的像素值大小。相反的你也可以绑定javascript来获取WebView的尺寸大小。
(六)窄列以及单列不在被支持(NARROW_COLUMNS and SINGLE_COLUMN nolonger supported)
在新的WebView中WebSettings.LayoutAlgorithm的NARROW_COLUMNS值将不再被支持。
[注]:在Android4.4或者更高的版本中这些APIs将不会被支持,即时你的targetSdkVersion设置成18或者更低,也不会起作用了。
通过以下方面可以处理这种变化:
1.改变程序风格(Alter the styles of your application)
如果你控制编写页面的HTML和CSS样式文件,改变设计内容可能是最有效的方法。例如:
<span style="font-size:18px;"> <pre style="word-wrap: break-word; white-space: pre-wrap;"></span>如果你没有为你的页面定义viewport属性,这个设置将是特别有用的。
2.使用新的文本自动大小缩放布局算法:(Using the new TEXT_AUTOSIZING layoutalgorithm)
如果你使用narrow columns来让一个桌面网页在移动设备上面更具可读性并且不能改变HTML的内容,那么是哦那个TEXT_AUTOSIZING algorithm可能更加适合而不是使用narrow columns方法。
此外之前弃用的SINGLE_COLUMNS在新版本WebView中也不支持使用了。
(七)在Javascript中处理用户触摸事件(Handing touch Events in Javascript)
如果你的网页在WebView中直接处理触摸事件,并且确定也处理touchcancel事件。但是有些场景touchcance调用也会出现一些问题。
1.当控件元素被触摸(touchstart和touchmove被调用)或者页面滚动的时候,touchcancel可能会抛出异常。
2.当控件元素被触摸(touchstart被调用)但是event.preventDefault()不被调用之前,touchcancel可能会抛出异常(WebView可能会认为你不想使用触摸事件)。
后面的文章一系列知识点,会专门封装一个WebView组件,这样用起来更加方便点,敬请期待…
[WebView学习之四]:迁移到Android4.4版本的WebView