Android WebView 開發教程

聲明在先:必須在AndroidMainfest.xml 裏面聲明權限,不然在Java裏面編寫的全部WebView瀏覽網頁的代碼都沒法正常使用javascript

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

1.WebView的使用

(a). 建立WebView的實例加入到Activity中html

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

或者在xml中配置WebViewjava

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

(b). 訪問網頁android

webview.loadUrl("https://www.baidu.com/");  

2.WebView API使用詳解

(a). 請求加載網頁部分

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

加載指定的data數據web

參數說明:數據庫

data  字符串String形式的數據 能夠經過base64編碼而來api

mineType data數據的 MIME類型, e.g. 'text/html'瀏覽器

encoding data數據的編碼格式安全

注意:cookie

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

2.encoding參數制定data參數是否爲base64或者 URL 編碼,若是data是base64編碼那麼 encoding必須填寫 "base64「。

 

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

中止加載頁面 

(b). 網頁的前進後退

public void goBack ()  // 頁面後退
public void goForward ()  // 頁面前進 
public void goBackOrForward (int steps) // 以當前的index爲起始點前進或者後退到歷史記錄中指定的steps,  若是steps爲負數則爲後退,正數則爲前進
public boolean canGoForward ()  // 判斷頁面是否可以前進
public boolean canGoBack ()  // 判斷頁面是否可以後退

(c). JavaScript操做

public void addJavascriptInterface (Object object, String name)  

當網頁須要和App進行交互時,能夠注入Java對象提供給JavaScritp調用.  Java對象提供相應的方法供js使用.

注意:在Android 4.2如下使用這個api會涉及到JavaScript安全問題, javascript能夠經過反射這個Java對象的相關類進行攻擊。

連接:Android WebView 總結 —— Java和JavaScript交互 

連接:Android 4.2版本如下使用WebView組件addJavascriptInterface方法存在JS漏洞

 

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

這個方法在Android 4.4系統引入,所以只能在Android4.4系統中才能使用,提供在當前頁面顯示上下文中異步執行javascript代碼

注意: 這個方法必須在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會有問題,會存在失效狀況。

(d). 網頁查找功能

public void findAllAsync (String find)  

異步執行查找網頁內包含的字符並設置高亮,查找結果會回調.

 

public void findNext (boolean forward)  

查找下一個匹配的字符

 

(e). WebView 事件回調監聽

public void setWebChromeClient (WebChromeClient client)  

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

 
public void setWebViewClient (WebViewClient client)  

主要通知客戶端app加載當前網頁時的各類時機狀態,onPageStart,onPageFinish,onReceiveError等事件。

3.WebViewClient,WebChromeClient

WebView 作爲承載網頁的載體控件,他在網頁顯示的過程當中會產生一些事件,並回調給咱們的應用程序,以便咱們在網頁加載過程當中作應用程序想處理的事情。好比說客戶端須要顯示網頁加載的進度、網頁加載發生錯誤等等事件。 WebView提供兩個事件回調類給應用層,分別爲WebViewClient,WebChromeClient開發者能夠繼承這兩個類,接手相應事件處理。WebViewClient 主要提供網頁加載各個階段的通知,好比網頁開始加載onPageStarted,網頁結束加載onPageFinished等;WebChromeClient主要提供網頁加載過程當中提供的數據內容,好比返回網頁的title。

(a).WebViewClient

--WebViewClient使用

建立WebViewClient實例並設置到WebView對象中,具體代碼參考以下:
webview.setWebViewClient(new WebViewClient () {
  @Override  
    public void onPageStarted(WebView view, String url, Bitmap favicon) {  
       // TODO  
    }  
  
    @Override  
    public void onPageFinished(WebView view, String url) {  
      // TODO  
    }  
});  

 

--WebViewClient API詳解

public boolean shouldOverrideUrlLoading(WebView view, String url)  
當加載的網頁須要重定向的時候就會回調這個函數告知咱們應用程序是否須要接管控制網頁加載,若是應用程序接管,而且return true意味着程序接管網頁加載,若是返回false讓webview本身處理。
 
注意:
(1) 當請求的方式是"POST"方式時這個回調是不會通知的。
(2) 當咱們訪問的地址須要咱們應用程序本身處理的時候,能夠在這裏截獲,好比咱們發現跳轉到的是一個market的連接,那麼咱們能夠直接跳轉到應用市場,或者其餘app。
 
public void onPageStarted(WebView view, String url, Bitmap favicon)  
當開始加載訪問的url時,會通知應用程序,對每一個main frame這個函數只會被調用一次,頁面包含iframe 或者framesets 不會另外調用一次onPageStarted,當網頁內內嵌的frame 發生改變時也不會調用onPageStarted。
注意: 當咱們經過loadUrl的方式從新加載一個網址時候,這時候會先調用onPageStarted再調用shouldOverrideUrlLoading,當咱們在打開的這個網址點擊一個link,這時候會先調用shouldOverrideUrlLoading 再調用onPageStarted。不過shouldOverrideUrlLoading不必定每次都被調用,只有須要的時候纔會被調用。
 
public void onPageFinished(WebView view, String url)  
當加載完當前頁面時會通知咱們的應用程序,這個函數只有在main frame狀況下才會被調用。

public void onLoadResource(WebView view, String url)  

 

通知應用程序WebView即將加載url 制定的資源
 
public WebResourceResponse shouldInterceptRequest(WebView view, String url)  

 通知應用程序內核即將加載url制定的資源,應用程序能夠返回本地的資源提供給內核,若本地處理返回數據,內核不從網絡上獲取數據。

注意:這個回調並不必定在UI線程執行,因此咱們須要注意在這裏操做View或者私有數據相關的動做。若是咱們須要改變網頁的背景,或者須要實現網頁頁面顏色定製化的需求,能夠在這個回調時機處理。
 
public void onReceivedError(WebView view, int errorCode,  String description, String failingUrl)  
當瀏覽器訪問制定的網址發生錯誤時會通知咱們應用程序,好比網絡錯誤。

參數說明:
@param view 接收WebViewClient的那個實例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),便是這個webview。
@param errorCode 錯誤號能夠在WebViewClient.ERROR_* 裏面找到對應的錯誤名稱。
@param description 描述錯誤的信息
@param failingUrl  當前訪問失敗的url,注意並不必定是咱們主url
 
注意:
在onReceiveError咱們能夠自定義網頁的錯誤頁面。
 
public void onFormResubmission(WebView view, Message dontResend, Message resend)  

 

若是瀏覽器須要從新發送POST請求,能夠經過這個時機來處理。默認是不從新發送數據。
 
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload)  
通知應用程序能夠將當前的url存儲在數據庫中,意味着當前的訪問url已經生效並被記錄在內核當中。這個函數在網頁加載過程當中只會被調用一次。注意網頁前進後退並不會回調這個函數。
 
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)  
通知應用程序WebView接收到了一個Http auth的請求,應用程序可使用supplied 設置webview的響應請求。默認行爲是cancel 本次請求。
 
public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)   

提供應用程序同步一個處理按鍵事件的機會,菜單快捷鍵須要被過濾掉。若是返回true,webview不處理該事件,若是返回false, webview會一直處理這個事件,所以在view 鏈上沒有一個父類能夠響應到這個事件。默認行爲是return false;

 

public void onScaleChanged(WebView view, float oldScale, float newScale)  
通知應用程序webview 要被scale。應用程序能夠處理改事件,好比調整適配屏幕。
 

(b).WebChromeClient 

--webChromeClient使用

webView.setWebChromeClient(new WebChromeClient() {});
--webChromeCilent API詳解
建立WebChromeClient實例並設置到WebView對象中,具體代碼參考以下: 
public void onProgressChanged(WebView view, int newProgress)  
通知應用程序當前網頁加載的進度。
 
public void onReceivedTitle(WebView view, String title)  
當document 的title變化時,會通知應用程序。注意:這個函數調用時機不肯定,有可能很早,有可能很晚,取決於網頁把title設置在什麼位置,大多數網頁通常把title設置到頁面的前面,所以不少狀況會比較早回調到這個函數。
 
public void onReceivedIcon(WebView view, Bitmap icon)  
當前頁面有個新的favicon時候,會回調這個函數。
 
public void onShowCustomView(View view, CustomViewCallback callback)  

 通知應用程序webview須要顯示一個custom view,主要是用在視頻全屏HTML5Video support。

參數說明:
@param view 即將要顯示的view
@param callback  當view 須要dismiss 則使用這個對象進行回調通知。
 
public void onHideCustomView()  
退出視頻通知

public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)  
請求建立一個新的窗口,若是咱們應用程序接管這個請求,必須返回true,而且建立一個新的webview來承載主窗口。
若是應用程序不處理,則須要返回false,默認行爲和返回false表現同樣。
參數說明:
@param view 請求建立新窗口的webview
@param isUserGesture 若是是true,則說明是來自用戶收拾操做行爲,好比用戶點擊連接
@param isDialog true 請求建立的新窗口必須是個dialog,而不是全屏的窗口。
@param resultMsg 當webview建立時須要發送一個消息。WebView.WebViewTransport.setWebView(WebView)
 
public void onRequestFocus(WebView view)  
webview請求獲得focus,發生這個主要是當前webview不是前臺狀態,是後臺webview。
 
public void onCloseWindow(WebView window)  
通知應用程序從關閉傳遞過來的webview並從view tree中remove。
 
public boolean onJsAlert(WebView view, String url, String message, JsResult result)  

通知應用程序顯示javascript alert對話框,若是應用程序返回true內核認爲應用程序處理這個消息,返回false,內核本身處理。

注意: 若是咱們應用接管處理, 則必須給出result的結果,result.cancel,result.comfirm必須調用其中以後,不然內核會hang住。
 
public boolean onJsConfirm(WebView view, String url, String message,  JsResult result)  
通知應用程序提供confirm 對話框。
參數說明同上onJsAlert
 
public boolean onJsBeforeUnload(WebView view, String url, String message,  JsResult result)  
通知應用程序顯示一個對話框,讓用戶選擇是否離開當前頁面,這個回調是javascript中的onbeforeunload事件,若是客戶端返回true,內核會認爲客戶端提供對話框。默認行爲是return false。
參數說明和以前介紹的onJsAlert()相同。
 
public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture)  
這個回調是私有回調, 當頁面須要請求打開系統的文件選擇器,則會回調這個方法,好比咱們須要上傳圖片,請求拍照,郵件的附件上傳等等操做。
若是不實現這個私有API,則上面的請求都將不會執行。
 

4.WebSettings

Android WebView提供展現網頁,也提供咱們應用程序對網頁加載的一些定製,好比咱們爲了減小網絡數據能夠設置當前加載的頁面不能顯示圖片。Android 提供管理WebView的一些setting的類WebSettings,在WebView對象被建立時WebSettings對象也會被同時建立,並附有默認的settings值. WebSettings對象能夠經過WebView.getSettings()得到。WebSettings的生命週期同WebView生命週期相同,若是WebView被destroy 則WebSettings應該被釋放,不然若是使用WebSettings繼續再操做的話, 會拋出異常IllegalStateException。
 
注意:調用WebSettings設置的全部函數是異步制定的,所以咱們設置某個狀態並不能立刻生效。
 

(a).WebSettings API詳解

public synchronized void setLoadsImagesAutomatically(boolean flag)  

設置當前webview是否須要加載圖片,這個標記控制整個webview的狀態,而且對全部的資源都採起這種策略。若是設置爲false 那麼訪問的當前網址中的因此圖片資源將不會被加載。默認值是true;經過配置這個方法的標誌,能夠實現瀏覽器的無圖模式和有圖模式的控制。

 
public synchronized void setBlockNetworkImage (boolean flag)  
當getLoadsImagesAutomatically返回true這個方法纔有效, 默認值爲:false;
 
public void setCacheMode(int mode)  
一個普通網頁的加載cache會被檢查,內容也會被從新校驗,第一次訪問網頁時,會存儲cache到本地,設置策略可讓網頁加載方式發生變化,cache模式有以下幾種:
LOAD_DEFAULT: 若是咱們應用程序沒有設置任何cachemode, 這個是默認的cache方式。 加載一張網頁會檢查是否有cache,若是有而且沒有過時則使用本地cache,不然從網絡上獲取。
LOAD_CACHE_ELSE_NETWORK: 使用cache資源,即便過時了也使用,若是沒有cache才從網絡上獲取。
LOAD_NO_CACHE: 不使用cache 所有從網絡上獲取
LOAD_CACHE_ONLY:  只使用cache上的內容。
 
public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) 

NORMAL:正常顯示,沒有渲染變化。 
SINGLE_COLUMN:把全部內容放到WebView組件等寬的一列中。   //這個是強制的,把網頁都擠變形了(基本不推薦使用) 
NARROW_COLUMNS:可能的話,使全部列的寬度不超過屏幕寬度。 //默認的
TEXT_AUTOSIZING: 這個在API 19及以後才能使用,目前不須要了解和使用.

 
public void setLoadWithOverviewMode(boolean overview)  
概覽模式的設置,默認指是false。
 
public synchronized void setJavaScriptEnabled (boolean flag)  
默認值是false.  若是咱們網頁須要javascript時,須要開啓這個設置,不然網頁加載不全。
 
 

5. WebView 使用 TIPS

(a).爲WebView自定義錯誤顯示界面:

覆寫WebViewClient中的onReceivedError()方法:

 
/** 
 * 顯示自定義錯誤提示頁面,用一個View覆蓋在WebView 
 */  
protected void showErrorPage() {  
    LinearLayout webParentView = (LinearLayout)mWebView.getParent();  
      
    initErrorPage();  
    while (webParentView.getChildCount() > 1) {  
        webParentView.removeViewAt(0);  
    }  
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);  
    webParentView.addView(mErrorView, 0, lp);  
    mIsErrorPage = true;  
}  
protected void hideErrorPage() {  
    LinearLayout webParentView = (LinearLayout)mWebView.getParent();  
      
    mIsErrorPage = false;  
    while (webParentView.getChildCount() > 1) {  
        webParentView.removeViewAt(0);  
    }  
}  
  
  
   protected void initErrorPage() {  
    if (mErrorView == null) {  
        mErrorView = View.inflate(this, R.layout.online_error, null);  
        Button button = (Button)mErrorView.findViewById(R.id.online_error_btn_retry);  
        button.setOnClickListener(new OnClickListener() {  
            public void onClick(View v) {  
                mWebView.reload();  
            }  
        });  
        mErrorView.setOnClickListener(null);  
    }  
}  

@Override  
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {   
  mErrorView.setVisibility(View.VISIBLE);  
  super.onReceivedError(view, errorCode, description, failingUrl);  
}          =

(b).WebView cookies 清理

CookieSyncManager.createInstance(this);   
CookieSyncManager.getInstance().startSync();   
CookieManager.getInstance().removeSessionCookie();   

(c).清理cache和歷史記錄

webView.clearCache(true);   
webView.clearHistory();  

(d).屏蔽長按事件

mWebView.setOnLongClickListener(new OnLongClickListener() {  
            
          @Override  
          public boolean onLongClick(View v) {  
              return true;  
          }  
});  

(e).Webview保留縮放功能,可是隱藏縮放控價

mWebView.getSettings().setSupportZoom(true);  
mWebView.getSettings().setBuiltInZoomControls(true);  
if (DeviceUtils.hasHoneycomb()) { 
    mWebView.getSettings().setDisplayZoomControls(false);  
}
注意:setDisplayZoomControls是在Android 3.0中新增的API.
相關文章
相關標籤/搜索