天天看點

安卓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)通路網頁

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

2) 前進後退

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調用的方法前加入一個注視:@JavaScript***重點内容***Interface; 在虛拟機當中 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方法:具體格式如下:

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

這裡寫代碼片
           

public void removeJavascriptInterface (String name)

删除addJavascripInterface時對webview注入的java對象. 此方法在不同的Android系統WebView會有問題,會存在失效情況。

4)網頁查找功能

public int findAll (String find)  PI在Android 4.1 就已經被去除, 在Android 4.1極其以上系統使用findAllAsync方法
這個API還存在bug 具體請見我的之前一篇博文Android WebView findAll bug

           

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占用的所有資源。

7) WebView 事件回調監聽

這裡寫代碼片
           

public void setWebChromeClient (WebChromeClient client)

主要通知用戶端app加載目前網頁的 title,Favicon,progress,javascript dialog等事件,通知用戶端處理這些相應的事件。

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

  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 * );  
        }  

        @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);  
        }  

    }  
}  
           

轉載請注明出處 http://blog.csdn.net/typename/article/details/39030091

有問題歡迎讨論