Android开发之WebView的使用(1)

WebView

目前android市场上的一些应用采用的开发方式大致分为三种:

> Native App - 用原生的Android控件开发出来的应用

> Web App - 使用网页开发的应用

> Hybrid App - 混合式的应用,原生的控件和网页混合开发

Hybrid App中实现的主要技术native组件与Javascript的数据交互以及实现。

概览:

Android WebView在Android平台上是一个特殊的View, 他能用来显示网页,
这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器。

WebView内部实现是采用渲染引擎(Webkit)来展示view的内容,提供网页前进后退,网页放大,缩小,搜索,前端开发者可以使用web inspector(Android 4.4系统支持,4.4一下可以采用 http://developer.android.com/guide/webapps/debugging.html )调试HTML,CSS,Javascript等等功能。

在Android 4.3系统及其以下WebView内部采用 Webkit 渲染引擎,在Android 4.4采用 chromium 渲染引擎来渲染View的内容。

WebView的基本使用

  • 创建WebView的实例加入到Activity view tree中
 WebView webview = new WebView(this);  
 setContentView(webview); 
  • 在layout xml中配置WebView
<Webview  
        id="@+id/webview"
        android:layout_width="match_parent"  
        android:layout_height="match_parent" >  
</Webview>  

在代码中:

WebView webView = (WebView)findViewById(R.id.webview)
  • 访问网页

    • 载入互联网网页:
    webview.loadUrl("http://developer.android.com/"); 
    
    • 载入应用中的网页,有一个网页在assets:
    webView.loadUrl("file:///android_asset/page.html"); 
    
  • 添加权限,网络访问权限

<uses-permission android:name="android.permission.INTERNET" />

系统默认会通过手机浏览器打开网页,为了能够直接通过WebView显示网页,则必须设置:

    webview.setWebViewClient(new WebViewClient()
    {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) 
        {
            view.loadUrl(url);                
            return true;
        }
    });

WebView使用详解

请求加载网页

加载指定的data数据

public void loadData (String data, String mimeType, String encoding)

参数说明:

data 字符串String形式的数据 可以通过base64编码而来,html格式字符串
Content-Type -> text/html; charset=ut-8
mineType data数据的 MIME类型
encoding data数据的编码格式

提示:
1.Javascript有同源限制,同源策略限制了一个源中加载文本或者脚本与来自其他源中的数据交互方式。
避免这种限制可以使用loadDataWithBaseURL()方法。

2.encoding参数制定data参数是否为base64或者 URL 编码,如果data是base64编码那么 encoding必须填写 "base64“。
官方文档:http://developer.android.com/reference/android/webkit/WebView.html

其他方法:

  • public void loadDataWithBaseURL (String baseUrl, String data,
    String mimeType, String encoding, String historyUrl) 使用baseUrl加载base URL的网页内容,baseUrl解决相关url使用Javascript相同源问题。

  • public void loadUrl (String url) 加载制定url的网页内容

  • public void loadUrl (String url, Map<String, String> additionalHttpHeaders) 加载制定url并携带http header数据。

  • public void reload () 重新加载页面

前进后退

  • public void goBack () 返回
  • public void goForward () 前进
  • public void goBackOrForward (int steps) 以当前的index为起始点前进或者后退到历史记录中指定的steps,如果steps为负数则为后退,正数则为前进
  • public boolean canGoForward () 是否可前进
  • public boolean canGoBack () 是否可返回

JavaScript操作

在webview添加对js的支持:

WebSettings setting = webView.getSettings();  
setting.setJavaScriptEnabled(true);//支持js

public void addJavascriptInterface (Object object, String name)
当网页需要和App进行交互时,可以注入Java对象提供给JavaScritp调用. Java对象提供相应的方法供js使用

提示(重要):
问题:在Android 4.2以下使用这个api会涉及到JavaScript安全问题,javascript可以通过反射这个java对象的相关类进行攻击。

解决:可以采用白名单的机制调用这个方法

在Android4.2极其以上系统需要给提供js调用的方法前加入一个注视:@JavaScriptInterface;
在虚拟机当中 Javascript调用Java方法会检测这个anotation,如果方法被标识@JavaScriptInterface则Javascript可以成功调用这个Java方法,否则调用不成功。

网页查找功能

  • public int findAll (String find) 这个API在Android 4.1 就已经被去除, 在Android 4.1极其以上系统使用findAllAsync方法
  • public void findAllAsync (String find) 异步执行查找网页内包含的字符并设置高亮,查找结果会回调.
  • public void findNext (boolean forward) 查找下一个匹配的字符

数据清除

  • public void clearCache (boolean includeDiskFiles) 清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
  • public void clearFormData () 这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
  • public void clearHistory () 清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
  • public void clearMatches () 清除网页查找的高亮匹配字符
  • public void clearView () 在Android 4.3及其以上系统这个api被丢弃了, 并且这个api大多数情况下会有bug,经常不能清除掉之前的渲染数据。官方建议通过loadUrl("about:blank")来实现这个功能

WebView的状态

  • public void onResume () 激活WebView为活跃状态,能正常执行网页的响应
  • public void onPause () 当页面被失去焦点被切换到后台不可见状态,需要执行onPause动过, onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。并且可以减少不必要的CPU和网络开销,可以达到省电、省流量、省资源的效果。
  • public void pauseTimers () 当应用程序被切换到后台我们使用了webview, 这个方法不仅仅针对当前的webview而是全局的全应用程序的webview,它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
  • public void resumeTimers () 恢复pauseTimers时的动作。
  • public void destroy () 这个方法必须在webview从view tree中删除之后才能被执行, 这个方法会通知native释放webview占用的所有资源。

WebView 事件回调监听

  • public void setWebChromeClient (WebChromeClient client) 主要通知客户端app加载当前网页的 title,Favicon,progress,javascript dialog等事件,通知客户端处理这些相应的事件。
  • public void setWebViewClient (WebViewClient client) 主要通知客户端app加载当前网页时的各种时机状态,onPageStart,onPageFinish,onReceiveError等事件。

例:

    package com.example.webviewdemo;  
      
    import android.annotation.SuppressLint;  
    import android.app.Activity;  
    import android.content.Context;  
    import android.graphics.Bitmap;  
    import android.os.Message;  
    import android.webkit.WebChromeClient;  
    import android.webkit.WebSettings;  
    import android.webkit.WebView;  
    import android.webkit.WebViewClient;  
      
    public class WebViewBase extends WebView {  
        private static final String DEFAULT_URL = "http://www.baidu.com/";  
        private Activity mActivity;  
        public WebViewBase(Context context) {  
            super(context);  
            mActivity = (Activity) context;  
            init(context);  
        }  
          
        @SuppressLint("SetJavaScriptEnabled")  
        private void init(Context context) {  
            WebSettings webSettings = this.getSettings();  
            webSettings.setJavaScriptEnabled(true);  
            webSettings.setSupportZoom(true);  
            //webSettings.setUseWideViewPort(true);  
            this.setWebViewClient(mWebViewClientBase);  
            this.setWebChromeClient(mWebChromeClientBase);  
            this.loadUrl(DEFAULT_URL);  
            this.onResume();  
        }  
          
        private WebViewClientBase mWebViewClientBase = new WebViewClientBase();  
          
        private class WebViewClientBase extends WebViewClient {  
      
            @Override  
            public boolean shouldOverrideUrlLoading(WebView view, String url) {  
                // TODO Auto-generated method stub  
                return super.shouldOverrideUrlLoading(view, url);  
            }  
      
            @Override  
            public void onPageStarted(WebView view, String url, Bitmap favicon) {  
                // TODO Auto-generated method stub  
                super.onPageStarted(view, url, favicon);  
            }  
      
            @Override  
            public void onPageFinished(WebView view, String url) {  
                // TODO Auto-generated method stub  
                super.onPageFinished(view, url);  
            }  
      
            @Override  
            public void onReceivedError(WebView view, int errorCode,  
                    String description, String failingUrl) {  
                // TODO Auto-generated method stub  
                super.onReceivedError(view, errorCode, description, failingUrl);  
            }  
      
            @Override  
            public void doUpdateVisitedHistory(WebView view, String url,  
                    boolean isReload) {  
                // TODO Auto-generated method stub  
                super.doUpdateVisitedHistory(view, url, isReload);  
            }  
        }  
          
        private WebChromeClientBase mWebChromeClientBase = new WebChromeClientBase();  
          
        private class WebChromeClientBase extends WebChromeClient {  
      
            @Override  
            public void onProgressChanged(WebView view, int newProgress) {  
                mActivity.setProgress(newProgress * 1000);  
            }  
      
            @Override  
            public void onReceivedTitle(WebView view, String title) {  
                // TODO Auto-generated method stub  
                super.onReceivedTitle(view, title);  
            }  
      
            @Override  
            public void onReceivedTouchIconUrl(WebView view, String url,  
                    boolean precomposed) {  
                // TODO Auto-generated method stub  
                super.onReceivedTouchIconUrl(view, url, precomposed);  
            }  
      
            @Override  
            public boolean onCreateWindow(WebView view, boolean isDialog,  
                    boolean isUserGesture, Message resultMsg) {  
                // TODO Auto-generated method stub  
                return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);  
            }  
              
        }  
    }

Android 5.0Lollipop新API

public static void enableSlowWholeDocumentDraw ()
Android 5.0 Webview默认提供减少内存占用支持,并且智能选择需要绘制的HTML document部门来提供性能。当然开发者可以在自己应用程序需要时关闭这个选项(enableSlowWholeDocumentDraw)。

推荐阅读更多精彩内容