Android Webview 開發詳解

          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中   

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. WebView webview = new WebView(this);  
  2. setContentView(webview);  

  (2)在xml中配置WebView

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. <Webview  
  2.     android:layout_width="match_parent"  
  3.     android:layout_height="match_parent" >  
  4. </Webview>  
  (3)訪問網頁

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. webview.loadUrl("http://developer.android.com/");  

2.WebView API使用詳解

   1)請求加載網頁部分
        
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  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

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)  
使用baseUrl加載base URL的網頁內容,baseUrl解決相關url使用Javascript相同源問題。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void loadUrl (String url)  
加載制定url的網頁內容

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void loadUrl (String url, Map<String, String> additionalHttpHeaders)  

加載制定url並攜帶http header數據。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void reload ()  

重新加載頁面

Tip(重要)

頁面所有資源會重新加載

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void stopLoading ()  


2) 前進後退

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void goBack ()  
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void goForward ()  
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void goBackOrForward (int steps)  
以當前的index爲起始點前進或者後退到歷史記錄中指定的steps,  如果steps爲負數則爲後退,正數則爲前進

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public boolean canGoForward ()  
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public boolean canGoBack ()  


3)JavaScript操作

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. 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:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. class JsObject {  
  2.    @JavascriptInterface  
  3.    public String toString() { return "injectedObject"; }  
  4. }  
  5. webView.addJavascriptInterface(new JsObject(), "injectedObject");  

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void evaluateJavascript (String script, ValueCallback<String> resultCallback)  
這個方法在Android 4.4系統引入,因此只能在Android4.4系統中才能使用,提供在當前頁面顯示上下文中異步執行javascript代碼

Tips(重要)

這個方法必須在UI線程調用,這個函數的回調也會在UI線程執行。

那麼在Android4.4一下如何執行javascrit代碼呢

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

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. webView.loadUrl("javascript:alert(injectedObject.toString())");  

其中javascript: 是執行javascript代碼的標識 , 後面是javascript語句。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void removeJavascriptInterface (String name)  
刪除addJavascripInterface時對webview注入的java對象. 此方法在不同的Android系統WebView會有問題,會存在失效情況。

4)網頁查找功能

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public int findAll (String find)  
這個API在Android 4.1 就已經被去除, 在Android 4.1極其以上系統使用findAllAsync方法

這個API還存在bug 具體請見我的之前一篇博文Android WebView findAll bug

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void findAllAsync (String find)  
異步執行查找網頁內包含的字符並設置高亮,查找結果會回調.

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void findNext (boolean forward)  
查找下一個匹配的字符

使用example:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public class TestFindListener implements android.webkit.WebView.FindListener {  
  2.     private FindListener mFindListener;  
  3.   
  4.     public TestFindListener(FindListener findListener) {  
  5.         mFindListener = findListener;  
  6.     }  
  7.   
  8.     @Override  
  9.     public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,  
  10.             boolean isDoneCounting) {  
  11.         mFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches, isDoneCounting);  
  12.     }  
  13. }  
  14.   
  15.    public void findAllAsync(String searchString) {  
  16.        if (android.os.Build.VERSION_CODES.JELLY_BEAN <= Build.VERSION.SDK_INT)  
  17.            mWebView.findAllAsync(searchString);  
  18.        else {  
  19.            int number = mWebView.findAll(searchString);  
  20.            if (mIKFindListener !=null)  
  21.                mIKFindListener.onFindResultReceived(number);  
  22.            fixedFindAllHighLight();  // 參見我之前一篇博文Android WebView API findAll bug  
  23.        }  
  24.    }  
  25.      
  26.    mWebView.findNext(forward);  

5)數據清除部分

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void clearCache (boolean includeDiskFiles)  
清除網頁訪問留下的緩存,由於內核緩存是全局的因此這個方法不僅僅針對webview而是針對整個應用程序.

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void clearFormData ()  
這個api僅僅清除自動完成填充的表單數據,並不會清除WebView存儲到本地的數據。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void clearHistory ()  
清除當前webview訪問的歷史記錄,只會webview訪問歷史記錄裏的所有記錄除了當前訪問記錄.

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void clearMatches ()  
清除網頁查找的高亮匹配字符

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void clearView ()  
在Android 4.3及其以上系統這個api被丟棄了, 並且這個api大多數情況下會有bug,經常不能清除掉之前的渲染數據。官方建議通過loadUrl("about:blank")來實現這個功能,陰雨需要重新加載一個頁面自然時間會收到影響。

6)WebView的狀態

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void onResume ()  
激活WebView爲活躍狀態,能正常執行網頁的響應

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void onPause ()  
當頁面被失去焦點被切換到後臺不可見狀態,需要執行onPause動過, onPause動作通知內核暫停所有的動作,比如DOM的解析、plugin的執行、JavaScript執行。並且可以減少不必要的CPU和網絡開銷,可以達到省電、省流量、省資源的效果。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void pauseTimers ()  

當應用程序被切換到後臺我們使用了webview, 這個方法不僅僅針對當前的webview而是全局的全應用程序的webview,它會暫停所有webview的layout,parsing,javascripttimer。降低CPU功耗。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void resumeTimers ()  
恢復pauseTimers時的動作。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void destroy ()  
Tips(重要)

這個方法必須在webview從view tree中刪除之後才能被執行, 這個方法會通知native釋放webview佔用的所有資源。

7) WebView 事件回調監聽

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void setWebChromeClient (WebChromeClient client)  
主要通知客戶端app加載當前網頁的 title,Favicon,progress,javascript dialog等事件,通知客戶端處理這些相應的事件。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public void setWebViewClient (WebViewClient client)  
主要通知客戶端app加載當前網頁時的各種時機狀態,onPageStart,onPageFinish,onReceiveError等事件。

8) Android 5.0 Lollipop 新API

public static void enableSlowWholeDocumentDraw ()

Android 5.0 Webview默認提供減少內存佔用支持,並且智能選擇需要繪製的HTML document部門來提供性能。 當然開發者可以在自己應用程序需要時關閉這個選項(enableSlowWholeDocumentDraw)。

3. WebView Demo

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. package com.example.webviewdemo;  
  2.   
  3. import android.annotation.SuppressLint;  
  4. import android.app.Activity;  
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.os.Message;  
  8. import android.webkit.WebChromeClient;  
  9. import android.webkit.WebSettings;  
  10. import android.webkit.WebView;  
  11. import android.webkit.WebViewClient;  
  12.   
  13. public class WebViewBase extends WebView {  
  14.     private static final String DEFAULT_URL = "http://www.ijinshan.com/";  
  15.     private Activity mActivity;  
  16.     public WebViewBase(Context context) {  
  17.         super(context);  
  18.         mActivity = (Activity) context;  
  19.         init(context);  
  20.     }  
  21.       
  22.     @SuppressLint("SetJavaScriptEnabled")  
  23.     private void init(Context context) {  
  24.         WebSettings webSettings = this.getSettings();  
  25.         webSettings.setJavaScriptEnabled(true);  
  26.         webSettings.setSupportZoom(true);  
  27.         //webSettings.setUseWideViewPort(true);  
  28.         this.setWebViewClient(mWebViewClientBase);  
  29.         this.setWebChromeClient(mWebChromeClientBase);  
  30.         this.loadUrl(DEFAULT_URL);  
  31.         this.onResume();  
  32.     }  
  33.       
  34.     private WebViewClientBase mWebViewClientBase = new WebViewClientBase();  
  35.       
  36.     private class WebViewClientBase extends WebViewClient {  
  37.   
  38.         @Override  
  39.         public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  40.             // TODO Auto-generated method stub  
  41.             return super.shouldOverrideUrlLoading(view, url);  
  42.         }  
  43.   
  44.         @Override  
  45.         public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  46.             // TODO Auto-generated method stub  
  47.             super.onPageStarted(view, url, favicon);  
  48.         }  
  49.   
  50.         @Override  
  51.         public void onPageFinished(WebView view, String url) {  
  52.             // TODO Auto-generated method stub  
  53.             super.onPageFinished(view, url);  
  54.         }  
  55.   
  56.         @Override  
  57.         public void onReceivedError(WebView view, int errorCode,  
  58.                 String description, String failingUrl) {  
  59.             // TODO Auto-generated method stub  
  60.             super.onReceivedError(view, errorCode, description, failingUrl);  
  61.         }  
  62.   
  63.         @Override  
  64.         public void doUpdateVisitedHistory(WebView view, String url,  
  65.                 boolean isReload) {  
  66.             // TODO Auto-generated method stub  
  67.             super.doUpdateVisitedHistory(view, url, isReload);  
  68.         }  
  69.     }  
  70.       
  71.     private WebChromeClientBase mWebChromeClientBase = new WebChromeClientBase();  
  72.       
  73.     private class WebChromeClientBase extends WebChromeClient {  
  74.   
  75.         @Override  
  76.         public void onProgressChanged(WebView view, int newProgress) {  
  77.             mActivity.setProgress(newProgress * 1000);  
  78.         }  
  79.   
  80.         @Override  
  81.         public void onReceivedTitle(WebView view, String title) {  
  82.             // TODO Auto-generated method stub  
  83.             super.onReceivedTitle(view, title);  
  84.         }  
  85.   
  86.         @Override  
  87.         public void onReceivedTouchIconUrl(WebView view, String url,  
  88.                 boolean precomposed) {  
  89.             // TODO Auto-generated method stub  
  90.             super.onReceivedTouchIconUrl(view, url, precomposed);  
  91.         }  
  92.   
  93.         @Override  
  94.         public boolean onCreateWindow(WebView view, boolean isDialog,  
  95.                 boolean isUserGesture, Message resultMsg) {  
  96.             // TODO Auto-generated method stub  
  97.             return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);  
  98.         }  
  99.           
  100.     }  
  101. }  

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. <uses-permission android:name="android.permission.INTERNET" />  


轉載請註明出處  http://blog.csdn.net/typename/article/details/39030091 powered by meichal zhao

有問題歡迎討論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章