(转载)Android WebView 开发详解(一)

前言#

WebView我们都使用过,但是怎么说呢,大部分人应该都是赶鸭子上架,例如像我这样的,需要用的时候就去查一下相关api,毕竟做原生app开发,webView用的确实不多,今天突然发现了这一点,觉得应该弥补一下这方面的不足,在网上看了一位博主分享之前分享的WebView介绍,非常细节,非常棒,必须要让更多的人看到。

复制过来的排版可能有些问题,可以直接去看原文。

正文#

转载请注明出处 http://blog.csdn.net/typename/article/details/39030091 powered by meichal zhao

概览:

Android WebView在Android平台上是一个特殊的View, 他能用来显示网页,这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器。WebView内部实现是采用渲染引擎来展示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的内容。
1.WebView的基本使用

(1)创建WebView的实例加入到Activity view tree中

 WebView webview = new WebView(this);  
 setContentView(webview);  

(2)在xml中配置WebView

<Webview  
        android:layout_width="match_parent"  
        android:layout_height="match_parent" >  
</Webview>  

(3)访问网页

 webview.loadUrl("http://developer.android.com/");  

2.WebView API使用详解
1)请求加载网页部分

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

加载指定的data数据

参数说明:

data 字符串String形式的数据 可以通过base64编码而来

mineType data数据的 MIME类型, e.g. 'text/html'

encoding data数据的编码格式

Tips:

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 ()  

重新加载页面

Tip(重要)

页面所有资源会重新加载

public void stopLoading ()  
  1. 前进后退

    public void goBack ()

    public void goForward ()

    public void goBackOrForward (int steps)

以当前的index为起始点前进或者后退到历史记录中指定的steps, 如果steps为负数则为后退,正数则为前进

public boolean canGoForward ()  

public boolean canGoBack ()  

3)JavaScript操作

public void addJavascriptInterface (Object object, String name)  

当网页需要和App进行交互时,可以注入Java对象提供给JavaScritp调用. Java对象提供相应的方法供js使用.

Tips(重要)

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

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

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

example:

class JsObject {  
   @JavascriptInterface  
   public String toString() { return "injectedObject"; }  
}  
webView.addJavascriptInterface(new JsObject(), "injectedObject");  

public void evaluateJavascript (String script, ValueCallback<String> resultCallback)  

这个方法在Android 4.4系统引入,因此只能在Android4.4系统中才能使用,提供在当前页面显示上下文中异步执行javascript代码

Tips(重要)

这个方法必须在UI线程调用,这个函数的回调也会在UI线程执行。

那么在Android4.4一下如何执行javascrit代码呢

可以通过 WebView提供的loadUrl方法:具体格式如下:

webView.loadUrl("javascript:alert(injectedObject.toString())");

其中javascript: 是执行javascript代码的标识 , 后面是javascript语句。

public void removeJavascriptInterface (String name)  

删除addJavascripInterface时对webview注入的java对象. 此方法在不同的Android系统WebView会有问题,会存在失效情况。

4)网页查找功能

public int findAll (String find)  

这个API在Android 4.1 就已经被去除, 在Android 4.1极其以上系统使用findAllAsync方法

这个API还存在bug 具体请见我的之前一篇博文Android WebView findAll bug

[java] view plain copy
在CODE上查看代码片派生到我的代码片

public void findAllAsync (String find)  

异步执行查找网页内包含的字符并设置高亮,查找结果会回调.

public void findNext (boolean forward)  

查找下一个匹配的字符

使用example:

public class TestFindListener implements android.webkit.WebView.FindListener {  
    private FindListener mFindListener;  
  
    public TestFindListener(FindListener findListener) {  
        mFindListener = findListener;  
    }  
  
    @Override  
    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,  
            boolean isDoneCounting) {  
        mFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches, isDoneCounting);  
    }  
}  
  
   public void findAllAsync(String searchString) {  
       if (android.os.Build.VERSION_CODES.JELLY_BEAN <= Build.VERSION.SDK_INT)  
           mWebView.findAllAsync(searchString);  
       else {  
           int number = mWebView.findAll(searchString);  
           if (mIKFindListener !=null)  
               mIKFindListener.onFindResultReceived(number);  
           fixedFindAllHighLight();  // 参见我之前一篇博文Android WebView API findAll bug  
       }  
   }  
     
   mWebView.findNext(forward);  

5)数据清除部分

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")来实现这个功能,阴雨需要重新加载一个页面自然时间会收到影响。

6)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 ()  

Tips(重要)

这个方法必须在webview从view tree中删除之后才能被执行, 这个方法会通知native释放webview占用的所有资源。

  1. WebView 事件回调监听

    public void setWebChromeClient (WebChromeClient client)

主要通知客户端app加载当前网页的 title,Favicon,progress,javascript dialog等事件,通知客户端处理这些相应的事件。

public void setWebViewClient (WebViewClient client)  

主要通知客户端app加载当前网页时的各种时机状态,onPageStart,onPageFinish,onReceiveError等事件。

  1. Android 5.0 Lollipop 新API

public static void enableSlowWholeDocumentDraw ()

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

  1. WebView Demo

    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.ijinshan.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);  
         }  
           
     }  
    

    }

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容