首页 > 代码库 > [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的新特性。如果你设置targetSdkVersion19或者更高时,那你就需要特别的注意。

         []:当你设置targetSdkVersion18或者更低的时候,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或者更低,也不会起作用了。

      如果定义HTMLviewport属性的有关信息请想看: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.outerWidthwindow.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)

                   如果你控制编写页面的HTMLCSS样式文件,改变设计内容可能是最有效的方法。例如:

<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.当控件元素被触摸(touchstarttouchmove被调用)或者页面滚动的时候,touchcancel可能会抛出异常。

        2.当控件元素被触摸(touchstart被调用)但是event.preventDefault()不被调用之前,touchcancel可能会抛出异常(WebView可能会认为你不想使用触摸事件)


后面的文章一系列知识点,会专门封装一个WebView组件,这样用起来更加方便点,敬请期待


[WebView学习之四]:迁移到Android4.4版本的WebView