(轉(zhuǎn)載)Android WebView 開(kāi)發(fā)詳解(一)

前言#

WebView我們都使用過(guò),但是怎么說(shuō)呢,大部分人應(yīng)該都是趕鴨子上架,例如像我這樣的,需要用的時(shí)候就去查一下相關(guān)api,畢竟做原生app開(kāi)發(fā),webView用的確實(shí)不多,今天突然發(fā)現(xiàn)了這一點(diǎn),覺(jué)得應(yīng)該彌補(bǔ)一下這方面的不足,在網(wǎng)上看了一位博主分享之前分享的WebView介紹,非常細(xì)節(jié),非常棒,必須要讓更多的人看到。

復(fù)制過(guò)來(lái)的排版可能有些問(wèn)題,可以直接去看原文。

正文#

轉(zhuǎn)載請(qǐng)注明出處 http://blog.csdn.net/typename/article/details/39030091 powered by meichal zhao

概覽:

Android WebView在Android平臺(tái)上是一個(gè)特殊的View, 他能用來(lái)顯示網(wǎng)頁(yè),這個(gè)類(lèi)可以被用來(lái)在你的app中僅僅顯示一張?jiān)诰€的網(wǎng)頁(yè),還可以用來(lái)開(kāi)發(fā)瀏覽器。WebView內(nèi)部實(shí)現(xiàn)是采用渲染引擎來(lái)展示view的內(nèi)容,提供網(wǎng)頁(yè)前進(jìn)后退,網(wǎng)頁(yè)放大,縮小,搜索,前端開(kāi)發(fā)者可以使用web inspector(Android 4.4系統(tǒng)支持,4.4一下可以采用http://developer.android.com/guide/webapps/debugging.html)調(diào)試HTML,CSS,JavaScript等等功能。在Android 4.3系統(tǒng)及其一下WebView內(nèi)部采用Webkit渲染引擎,在Android 4.4采用chromium 渲染引擎來(lái)渲染View的內(nèi)容。
1.WebView的基本使用

(1)創(chuàng)建WebView的實(shí)例加入到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)訪問(wèn)網(wǎng)頁(yè)

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

2.WebView API使用詳解
1)請(qǐng)求加載網(wǎng)頁(yè)部分

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

加載指定的data數(shù)據(jù)

參數(shù)說(shuō)明:

data 字符串String形式的數(shù)據(jù) 可以通過(guò)base64編碼而來(lái)

mineType data數(shù)據(jù)的 MIME類(lèi)型, e.g. 'text/html'

encoding data數(shù)據(jù)的編碼格式

Tips:

1.Javascript有同源限制,同源策略限制了一個(gè)源中加載文本或者腳本與來(lái)自其他源中的數(shù)據(jù)交互方式。避免這種限制可以使用loadDataWithBaseURL()方法。

2.encoding參數(shù)制定data參數(shù)是否為base64或者 URL 編碼,如果data是base64編碼那么 encoding必須填寫(xiě) "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的網(wǎng)頁(yè)內(nèi)容,baseUrl解決相關(guān)url使用Javascript相同源問(wèn)題。

public void loadUrl (String url)  

加載制定url的網(wǎng)頁(yè)內(nèi)容

public void loadUrl (String url, Map<String, String> additionalHttpHeaders)  

加載制定url并攜帶http header數(shù)據(jù)。

public void reload ()  

重新加載頁(yè)面

Tip(重要)

頁(yè)面所有資源會(huì)重新加載

public void stopLoading ()  
  1. 前進(jìn)后退

    public void goBack ()

    public void goForward ()

    public void goBackOrForward (int steps)

以當(dāng)前的index為起始點(diǎn)前進(jìn)或者后退到歷史記錄中指定的steps, 如果steps為負(fù)數(shù)則為后退,正數(shù)則為前進(jìn)

public boolean canGoForward ()  

public boolean canGoBack ()  

3)JavaScript操作

public void addJavascriptInterface (Object object, String name)  

當(dāng)網(wǎng)頁(yè)需要和App進(jìn)行交互時(shí),可以注入Java對(duì)象提供給JavaScritp調(diào)用. Java對(duì)象提供相應(yīng)的方法供js使用.

Tips(重要)

問(wèn)題:在Android 4.2以下使用這個(gè)api會(huì)涉及到JavaScript安全問(wèn)題, javascript可以通過(guò)反射這個(gè)Java對(duì)象的相關(guān)類(lèi)進(jìn)行攻擊。

解決:可以采用白名單的機(jī)制調(diào)用這個(gè)方法.

在Android4.2極其以上系統(tǒng)需要給提供js調(diào)用的方法前加入一個(gè)注視:@JavaScriptInterface; 在虛擬機(jī)當(dāng)中 Javascript調(diào)用Java方法會(huì)檢測(cè)這個(gè)anotation,如果方法被標(biāo)識(shí)@JavaScriptInterface則Javascript可以成功調(diào)用這個(gè)Java方法,否則調(diào)用不成功。

example:

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

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

這個(gè)方法在Android 4.4系統(tǒng)引入,因此只能在Android4.4系統(tǒng)中才能使用,提供在當(dāng)前頁(yè)面顯示上下文中異步執(zhí)行javascript代碼

Tips(重要)

這個(gè)方法必須在UI線程調(diào)用,這個(gè)函數(shù)的回調(diào)也會(huì)在UI線程執(zhí)行。

那么在Android4.4一下如何執(zhí)行javascrit代碼呢

可以通過(guò) WebView提供的loadUrl方法:具體格式如下:

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

其中javascript: 是執(zhí)行javascript代碼的標(biāo)識(shí) , 后面是javascript語(yǔ)句。

public void removeJavascriptInterface (String name)  

刪除addJavascripInterface時(shí)對(duì)webview注入的java對(duì)象. 此方法在不同的Android系統(tǒng)WebView會(huì)有問(wèn)題,會(huì)存在失效情況。

4)網(wǎng)頁(yè)查找功能

public int findAll (String find)  

這個(gè)API在Android 4.1 就已經(jīng)被去除, 在Android 4.1極其以上系統(tǒng)使用findAllAsync方法

這個(gè)API還存在bug 具體請(qǐng)見(jiàn)我的之前一篇博文Android WebView findAll bug

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

public void findAllAsync (String find)  

異步執(zhí)行查找網(wǎng)頁(yè)內(nèi)包含的字符并設(shè)置高亮,查找結(jié)果會(huì)回調(diào).

public void findNext (boolean forward)  

查找下一個(gè)匹配的字符

使用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();  // 參見(jiàn)我之前一篇博文Android WebView API findAll bug  
       }  
   }  
     
   mWebView.findNext(forward);  

5)數(shù)據(jù)清除部分

public void clearCache (boolean includeDiskFiles)  

清除網(wǎng)頁(yè)訪問(wèn)留下的緩存,由于內(nèi)核緩存是全局的因此這個(gè)方法不僅僅針對(duì)webview而是針對(duì)整個(gè)應(yīng)用程序.

public void clearFormData ()  

這個(gè)api僅僅清除自動(dòng)完成填充的表單數(shù)據(jù),并不會(huì)清除WebView存儲(chǔ)到本地的數(shù)據(jù)。

public void clearHistory ()  

清除當(dāng)前webview訪問(wèn)的歷史記錄,只會(huì)webview訪問(wèn)歷史記錄里的所有記錄除了當(dāng)前訪問(wèn)記錄.

public void clearMatches ()  

清除網(wǎng)頁(yè)查找的高亮匹配字符

public void clearView ()  

在Android 4.3及其以上系統(tǒng)這個(gè)api被丟棄了, 并且這個(gè)api大多數(shù)情況下會(huì)有bug,經(jīng)常不能清除掉之前的渲染數(shù)據(jù)。官方建議通過(guò)loadUrl("about:blank")來(lái)實(shí)現(xiàn)這個(gè)功能,陰雨需要重新加載一個(gè)頁(yè)面自然時(shí)間會(huì)收到影響。

6)WebView的狀態(tài)

public void onResume ()  

激活WebView為活躍狀態(tài),能正常執(zhí)行網(wǎng)頁(yè)的響應(yīng)

public void onPause ()  

當(dāng)頁(yè)面被失去焦點(diǎn)被切換到后臺(tái)不可見(jiàn)狀態(tài),需要執(zhí)行onPause動(dòng)過(guò), onPause動(dòng)作通知內(nèi)核暫停所有的動(dòng)作,比如DOM的解析、plugin的執(zhí)行、JavaScript執(zhí)行。并且可以減少不必要的CPU和網(wǎng)絡(luò)開(kāi)銷(xiāo),可以達(dá)到省電、省流量、省資源的效果。

public void pauseTimers ()  

當(dāng)應(yīng)用程序被切換到后臺(tái)我們使用了webview, 這個(gè)方法不僅僅針對(duì)當(dāng)前的webview而是全局的全應(yīng)用程序的webview,它會(huì)暫停所有webview的layout,parsing,javascripttimer。降低CPU功耗。

public void resumeTimers ()  

恢復(fù)pauseTimers時(shí)的動(dòng)作。

public void destroy ()  

Tips(重要)

這個(gè)方法必須在webview從view tree中刪除之后才能被執(zhí)行, 這個(gè)方法會(huì)通知native釋放webview占用的所有資源。

  1. WebView 事件回調(diào)監(jiān)聽(tīng)

    public void setWebChromeClient (WebChromeClient client)

主要通知客戶端app加載當(dāng)前網(wǎng)頁(yè)的 title,F(xiàn)avicon,progress,javascript dialog等事件,通知客戶端處理這些相應(yīng)的事件。

public void setWebViewClient (WebViewClient client)  

主要通知客戶端app加載當(dāng)前網(wǎng)頁(yè)時(shí)的各種時(shí)機(jī)狀態(tài),onPageStart,onPageFinish,onReceiveError等事件。

  1. Android 5.0 Lollipop 新API

public static void enableSlowWholeDocumentDraw ()

Android 5.0 Webview默認(rèn)提供減少內(nèi)存占用支持,并且智能選擇需要繪制的HTML document部門(mén)來(lái)提供性能。 當(dāng)然開(kāi)發(fā)者可以在自己應(yīng)用程序需要時(shí)關(guān)閉這個(gè)選項(xiàng)(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" />

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,384評(píng)論 0 17
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評(píng)論 19 139
  • 一、WebView 谷歌提供的系統(tǒng)組件,用來(lái)加載和展現(xiàn)html網(wǎng)頁(yè),其采用webkit內(nèi)核驅(qū)動(dòng),來(lái)實(shí)現(xiàn)網(wǎng)頁(yè)瀏覽功能...
    閑庭閱讀 7,215評(píng)論 2 12
  • 煩惱俱樂(lè)部(2)無(wú)種族開(kāi)放日 “你的眼睛像撒旦的葡萄,你的身體像惡魔的圍脖,你的血液像冰鎮(zhèn)的毒酒,歐耶耶……我死于...
    雨落荒原閱讀 1,488評(píng)論 5 15

友情鏈接更多精彩內(nèi)容