WebView使用詳解(二)——WebViewClient與經常使用事件監聽

 

關閉
 

WebView使用詳解(二)——WebViewClient與經常使用事件監聽 

 分類:
 

目錄(?)[+]java

 

前言:生活的艱難,更會激發對夢想的渴望,但艱難的生活卻每每會成爲夢想的絆腳石

mysql

相關文章:
一、《WebView使用詳解(一)——Native與JS相互調用(附JadX反編譯)》
二、《WebView使用詳解(二)——WebViewClient與經常使用事件監聽》
三、《WebView使用詳解(三)——WebChromeClient與LoadData補充》linux

 

上篇給你們簡單講了Webview中Native代碼與JS相互調用的方法,這篇咱們再講講有關各類攔截與處理的東東。android

1、WebViewClient

一、概述

前面咱們雖然實現了交互,但可能咱們會有一個很簡單的需求,就是在開始加載網頁的時候顯示進度條,加載結束之後隱藏進度條,這要怎麼作? 
這些簡單的需求,Android開發的老人們確定都已經想到了,這些有關各類事件的回調都被封裝在WebViewClient類中了,在WebViewClient中有各類的回調方法,就是在某個事件發生時供咱們監聽 
使用方法以下:

 

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  4.         super.onPageStarted(view, url, favicon);  
  5.         Log.d(TAG,"onPageStarted");  
  6.     }  
  7.   
  8.     @Override  
  9.     public void onPageFinished(WebView view, String url) {  
  10.         super.onPageFinished(view, url);  
  11.         Log.d(TAG,"onPageFinished");  
  12.     }  
  13. });  
直接調用WebView.setWebViewClient方法便可設置WebViewClient回調,這裏重寫的兩個函數,onPageStarted會在WebView開始加載網頁時調用,onPageFinished會在加載結束時調用。這兩個函數就能夠完成咱們開篇時的需求:在開始加載時顯示進度條,在結束加載時隱藏進度條。

二、WebViewClient中函數概述

在WebViewClient中除了上面咱們列舉出的onPageStarted、onPageFinished還有不少其它函數,分別是:
[java]  view plain  copy
  1. /** 
  2.  * 在開始加載網頁時會回調 
  3.  */  
  4. public void onPageStarted(WebView view, String url, Bitmap favicon)   
  5. /** 
  6.  * 在結束加載網頁時會回調 
  7.  */  
  8. public void onPageFinished(WebView view, String url)  
  9. /** 
  10.  * 攔截 url 跳轉,在裏邊添加點擊連接跳轉或者操做 
  11.  */  
  12. public boolean shouldOverrideUrlLoading(WebView view, String url)  
  13. /** 
  14.  * 加載錯誤的時候會回調,在其中可作錯誤處理,好比再請求加載一次,或者提示404的錯誤頁面 
  15.  */  
  16. public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)  
  17. /** 
  18.  * 當接收到https錯誤時,會回調此函數,在其中能夠作錯誤處理 
  19.  */  
  20. public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)  
  21. /** 
  22.  * 在每一次請求資源時,都會經過這個函數來回調 
  23.  */  
  24. public WebResourceResponse shouldInterceptRequest(WebView view,  
  25.         String url) {  
  26.     return null;  
  27. }  
上面的方法比較多,咱們一個個來看

三、WebViewClient之onPageStarted與onPageFinished

onPageStarted:通知主程序頁面當前開始加載。該方法只有在加載main frame時加載一次,若是一個頁面有多個frame,onPageStarted只在加載main frame時調用一次。也意味着若內置frame發生變化,onPageStarted不會被調用,如:在iframe中打開url連接。 
onPageFinished:通知主程序頁面加載結束。方法只被main frame調用一次。 
咱們就利用上面的想法來舉個例子:開始加載時顯示加載圓圈,結束加載時隱藏加載圓圈
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.loadUrl("http://blog.csdn.net/harvic880925");  
  16.         mWebView.setWebViewClient(new WebViewClient(){  
  17.   
  18.             @Override  
  19.             public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  20.                 mWebView.loadUrl(url);  
  21.                 return true;  
  22.             }  
  23.   
  24.             @Override  
  25.             public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  26.                 super.onPageStarted(view, url, favicon);  
  27.                 mProgressDialog.show();  
  28.             }  
  29.   
  30.             @Override  
  31.             public void onPageFinished(WebView view, String url) {  
  32.                 super.onPageFinished(view, url);  
  33.                 mProgressDialog.hide();  
  34.             }  
  35.         });  
  36.     }  
  37. }  
效果圖以下:

 

從效果圖中能夠明顯看出,在加載頁面的時候會顯示圓形加載框,在加載成功之後會隱藏加載框。程序員

四、WebViewClient之shouldOverrideUrlLoading

該函數的完整聲明以下:

 

 

[java]  view plain  copy
  1. public boolean shouldOverrideUrlLoading(WebView view, String url)  
這個函數會在加載超連接時回調過來;因此經過重寫shouldOverrideUrlLoading,能夠實現對網頁中超連接的攔截; 
返回值是boolean類型,表示是否屏蔽WebView繼續加載URL的默認行爲,由於這個函數是WebView加載URL前回調的,因此若是咱們return true,則WebView接下來就不會再加載這個URL了,全部處理都須要在WebView中操做,包含加載。若是咱們return false,則系統就認爲上層沒有作處理,接下來仍是會繼續加載這個URL的。WebViewClient默認就是return false的:
[java]  view plain  copy
  1. public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  2.        return false;  
  3. }  

(1)、如何在WebView中加載在線網址 

在上一篇中,咱們提到,若是要在WebView中加載在線網址,必須重寫WebViewClient 
如今網上鋪天蓋地的都是重寫shouldOverrideUrlLoading來將URL加載進WebView,但在用多了WebView之後會發現,直接下面這樣寫,就能夠實如今WebVIew中加載網頁:
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.setWebViewClient(new WebViewClient());  
  16.   
  17.         mWebView.loadUrl("http://blog.csdn.net/harvic880925");  
  18.     }  
  19. }  
效果圖以下:

 

從效果圖中能夠看出即僅僅設置WebViewClient對象,使用它的默認回調就能夠實如今WebView中加載在線URL了:web

 

[plain]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient());  

(2)、shouldOverrideUrlLoading用途 

因爲每次超連接在加載前都會先走shouldOverrideUrlLoading回調,因此咱們若是想攔截某個URL,將其轉換成其它URL能夠在這裏作。 
好比,咱們攔截全部包含「blog.csdn.net」的地址,將其替換成」www.baidu.com」: 
效果圖以下:

 

代碼以下:面試

 

[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.setWebViewClient(new WebViewClient(){  
  16.             @Override  
  17.             public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  18.                 if (url.contains("blog.csdn.net")){  
  19.                     view.loadUrl("http://www.baidu.com");  
  20.                 }else {  
  21.                     view.loadUrl(url);  
  22.                 }  
  23.                 return true;  
  24.             }  
  25.         });  
  26.   
  27.         mWebView.loadUrl("http://blog.csdn.net/harvic880925");  
  28.     }  
  29. }  
最關鍵的位置在:
[java]  view plain  copy
  1. public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  2.    if (url.contains("blog.csdn.net")){  
  3.         view.loadUrl("http://www.baidu.com");  
  4.     }else {  
  5.         view.loadUrl(url);  
  6.     }  
  7.    return true;  
  8. }  
若是在當前webview加載的url中包含「blog.csdn.net」,則將其轉換成」www.baidu.com」 
這裏須要很是注意的是:若是咱們在shouldOverrideUrlLoading中return true,就表示告訴系統咱們已經攔截了URL並作處理,不須要再觸發系統默認的行爲()在WebView中加載URL;因此對於其它URL咱們須要在else裏從新調用view.loadUrl(url)來加載;否則WebView將會白屏,由於這個URL根本就沒有加載進WebView,在shouldOverrideUrlLoading這就被咱們攔截掉了。 
那麼問題來了,在咱們return true了之後,WebView還會請求網絡嗎?咱們來抓下請求:

從請求中能夠看到,咱們雖然攔截了」http://blog.csdn.net/harvic880925「可是仍然仍是會請求網絡的。只是請求之後結果並無經過WebView加載。 
那問題來了,若是咱們return false呢,若是咱們return false的話,是不須要else語句的,由於系統默認會加載這個URL,因此上面的語句與下面的意義相等:

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  4.         if (url.contains("blog.csdn.net")){  
  5.             view.loadUrl("http://www.baidu.com");  
  6.         }  
  7.         return false;  
  8.     }  
  9. }      
因此相對而言,咱們使用return false好像更方便,只須要對須要攔截的URL進行攔截,攔截之後,讓WebView處理默認操做便可。 
因此結論來了:
在利用shouldOverrideUrlLoading來攔截URL時,若是return true,則會屏蔽系統默認的顯示URL結果的行爲,不須要處理的URL也須要調用loadUrl()來加載進WebVIew,否則就會出現白屏;若是return false,則系統默認的加載URL行爲是不會被屏蔽的,因此通常建議你們return false,咱們只關心咱們關心的攔截內容,對於不攔截的內容,讓系統本身來處理便可。

五、WebViewClient之onReceivedError

onReceivedError的完整聲明以下:

 

 

[java]  view plain  copy
  1. public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)  
加載錯誤的時候會產生這個回調,在其中可作錯誤處理,好比咱們能夠加載一個錯誤提示頁面 
這裏有四個參數:
  • WebView view:當前的WebView實例
  • int errorCode:錯誤碼
  • String description:錯誤描述
  • String failingUrl:當前出錯的URL
咱們能夠先寫一個錯誤提示的本地頁面:(error.html)
[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>Title</title>  
  6. </head>  
  7. <body>  
  8.     <h1 id="h">啊哈,出錯了……</h1>  
  9. </body>  
  10. </html>  
而後在加載返回錯誤時,從新加載錯誤頁面
[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  
  4.         super.onReceivedError(view, errorCode, description, failingUrl);  
  5.         mWebView.loadUrl("file:///android_asset/error.html");  
  6.     }  
  7. });  
效果圖以下:

 

 

源碼在文章底部給出

六、WebViewClient之onReceivedSslError

咱們知道HTTPS協議是經過SSL來通訊的,因此當使用HTTPS通訊的網址(以https://開頭的網站)出現錯誤時,就會經過onReceivedSslError回調通知過來,它的函數聲明爲:

 

 

[java]  view plain  copy
  1. /** 
  2.  * 當接收到https錯誤時,會回調此函數,在其中能夠作錯誤處理 
  3.  */  
  4. public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)  
  • WebView view:當前的WebView實例
  • SslErrorHandler handler:當前處理錯誤的Handler,它只有兩個函數SslErrorHandler.proceed()和SslErrorHandler.cancel(),SslErrorHandler.proceed()表示忽略錯誤繼續加載,SslErrorHandler.cancel()表示取消加載。在onReceivedSslError的默認實現中是使用的SslErrorHandler.cancel()來取消加載,因此一旦出來SSL錯誤,HTTPS網站就會被取消加載了,若是想忽略錯誤繼續加載就只有重寫onReceivedSslError,並在其中調用SslErrorHandler.proceed()
  • SslError error:當前的的錯誤對象,SslError包含了當前SSL錯誤的基本全部信息,你們本身去看下它的方法吧,這裏就再也不展開了。

示例(1)、默認加載SSL出錯的網站——出現空白頁面 

咱們先舉個例子來看下默認狀況下加載SSL有錯的網站,WebView的表現是怎樣的:(12306是經過Https協議來傳輸的,可是它的SSL證書是有問題的,因此咱們就以12306網站爲例)
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.setWebViewClient(new WebViewClient(){  
  16.             @Override  
  17.             public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
  18.                 super.onReceivedSslError(view, handler, error);  
  19.                 Log.e(TAG,"sslError:"+error.toString());  
  20.             }  
  21.   
  22.         mWebView.loadUrl("https://www.12306.cn/");  
  23.     }  
  24. }  
在這裏僅僅重寫onReceivedSslError,並調用super.onReceivedSslError(view, handler, error);來調用默認的處理方式,而後把錯誤日誌打出來:

錯誤日誌以下:

 

示例(2)、使用SslErrorHandler.proceed()來繼續加載

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
  4. //      必定要註釋掉!      
  5. //      super.onReceivedSslError(view, handler, error);  
  6.         handler.proceed();  
  7.         Log.e(TAG,"sslError:"+error.toString());  
  8.     }  
  9. });  
這裏作了兩個改變: 
第一:註釋掉super.onReceivedSslError(view, handler, error);,取消系統的默認行爲,咱們看源碼,能夠發如今WebViewClient中onReceivedSslError的默認實現是這樣的:
[java]  view plain  copy
  1. public void onReceivedSslError(WebView view, SslErrorHandler handler,  
  2.         SslError error) {  
  3.     handler.cancel();  
  4. }  
因此默認是取消繼續加載的,因此咱們必須註釋掉super.onReceivedSslError(view, handler, error)來取消這個默認行爲! 
第二:調用handler.proceed();來忽略錯誤繼續加載頁面。 
因此此時的效果圖爲:

示例(3):在SSL發生錯誤時,onReceivedError會被回調嗎?——不會 

你們可能還有一個疑問:當SSL發生錯誤時,咱們說會回調onReceivedSslError,咱們前面還說了一個出錯時會回調的函數:onReceivedError,那麼問題來了,當出現SSL錯誤時onReceivedError會被回調嗎? 
答案是不會的,咱們來作個實驗:

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
  4. //                super.onReceivedSslError(view, handler, error);  
  5.         handler.proceed();  
  6.         Log.e(TAG,"sslError:"+error.toString());  
  7.     }  
  8.   
  9.     @Override  
  10.     public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  
  11.         super.onReceivedError(view, errorCode, description, failingUrl);  
  12.         Log.e(TAG,"onReceivedError:"+errorCode+"  "+description);  
  13.     }  
  14. });  

在代碼中咱們同時使用onReceivedSslError和onReceivedError來接收錯誤,看下在出錯時,哪一個函數中會打出LOG,結果的日誌以下:

 

從日誌中明顯能夠看出,只有onReceivedSslError的接收日誌,因此在SSL出錯時,是不會觸發onReceivedError回調的
因此對於onReceivedSslError結論來了:
當出現SSL錯誤時,WebView默認是取消加載當前頁面,只有去掉onReceivedSslError的默認操做,而後添加SslErrorHandler.proceed()才能繼續加載出錯頁面
當HTTPS傳輸出現SSL錯誤時,錯誤會只經過onReceivedSslError回調傳過來算法

七、WebViewClient之shouldInterceptRequest

在每一次請求資源時,都會經過這個函數來回調,好比超連接、JS文件、CSS文件、圖片等,也就是說瀏覽器中每一次請求資源時,都會回調回來,不管任何資源!可是必須注意的是shouldInterceptRequest函數是在非UI線程中執行的,在其中不能直接作UI操做,若是須要作UI操做,則須要利用Handler來實現,該函數聲明以下:

 

 

[java]  view plain  copy
  1. public WebResourceResponse shouldInterceptRequest(WebView view,  
  2.         String url) {  
  3.     return null;  
  4. }  
該函數會在請求資源前調用,咱們能夠經過返回WebResourceResponse的處理結果來讓WebView直接使用咱們的處理結果。若是咱們不想處理,則直接返回null,系統會繼續加載該資源。 
利用這個特性,咱們能夠解決一個需求:假如網頁中須要加載本地的圖片,咱們就能夠經過攔截shouldInterceptRequest,並返回結果便可 
好比下面的一段HTML代碼中,img字段加載圖片的地址是:http://localhost/qijian.png,這是我自定義的一個網址,在Android中,當發現要加載這個地址的資源時,咱們將它換成本地的圖片
[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>Title</title>  
  6. </head>  
  7. <body>  
  8.     <h1 id="h">歡迎光臨啓艦的blog</h1>  
  9.     <img src="http://localhost/qijian.png"/>  
  10. </body>  
  11. </html>  
而後是Native代碼:
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.   
  16.         mWebView.setWebViewClient(new WebViewClient(){  
  17.             @Override  
  18.             public WebResourceResponse shouldInterceptRequest(WebView view, String url) {  
  19.                 try {  
  20.                     if (url.equals("http://localhost/qijian.png")) {  
  21.                         AssetFileDescriptor fileDescriptor =  getAssets().openFd("s07.jpg");  
  22.                         InputStream stream = fileDescriptor.createInputStream();  
  23.                         WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);  
  24.                         return response;  
  25.                     }  
  26.                 }catch (Exception e){  
  27.                     Log.e(TAG,e.getMessage());  
  28.                 }  
  29.                 return super.shouldInterceptRequest(view, url);  
  30.             }  
  31.         });  
  32.   
  33.         mWebView.loadUrl("file:///android_asset/web.html");  
  34. }          
這裏代碼比較容易理解,當發現當前加載資源的url是咱們自定義的http://localhost/qijian.png時,就直接將本地的圖片s07.jpg做爲結果返回。有關使用WebResourceResponse來構造結果的方法,我這裏就再也不展開了,內容實在是太多了,想具體瞭解針對不一樣狀況如何返回結果的話,本身搜下相關資料吧。 
結果圖以下:

 

 

七、WebViewClient之其他函數

上面講了經常使用的大部分函數,還些一些函數,並不怎麼用,這裏因爲篇幅有限就再也不講了,把函數聲明和做用列出來供你們參考

 

 

[java]  view plain  copy
  1. /** 
  2.  * 在加載頁面資源時會調用,每個資源(好比圖片)的加載都會調用一次 
  3.  */  
  4. public void onLoadResource(WebView view, String url)   
  5.  /** 
  6.  *  (WebView發生改變時調用)  
  7.  *  能夠參考http://www.it1352.com/191180.html的用法 
  8.  */  
  9.  public void onScaleChanged(WebView view, float oldScale, float newScale)  
  10.  /** 
  11.  * 重寫此方法纔可以處理在瀏覽器中的按鍵事件。 
  12.  * 是否讓主程序同步處理Key Event事件,如過濾菜單快捷鍵的Key Event事件。 
  13.  * 若是返回true,WebView不會處理Key Event, 
  14.  * 若是返回false,Key Event老是由WebView處理。默認:false 
  15.  */  
  16. public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)  
  17.  /** 
  18.  * 是否重發POST請求數據,默認不重發。 
  19.  */  
  20. onFormResubmission(WebView view, Message dontResend, Message resend)  
  21.  /** 
  22.  * 更新訪問歷史 
  23.  */  
  24. doUpdateVisitedHistory(WebView view, String url, boolean isReload)  
  25.  /** 
  26.  * 通知主程序輸入事件不是由WebView調用。是否讓主程序處理WebView未處理的Input Event。 
  27.  * 除了系統按鍵,WebView老是消耗掉輸入事件或shouldOverrideKeyEvent返回true。 
  28.  * 該方法由event 分發異步調用。注意:若是事件爲MotionEvent,則事件的生命週期只存在方法調用過程當中, 
  29.  * 若是WebViewClient想要使用這個Event,則須要複製Event對象。 
  30.  */  
  31. onUnhandledInputEvent(WebView view, InputEvent event)  
  32.  /** 
  33.  * 通知主程序執行了自動登陸請求。 
  34.  */  
  35. onReceivedLoginRequest(WebView view, String realm, String account, String args)  
  36. /** 
  37.  * 通知主程序:WebView接收HTTP認證請求,主程序可使用HttpAuthHandler爲請求設置WebView響應。默認取消請求。 
  38.  */  
  39. onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)  
  40. /** 
  41.  * 通知主程序處理SSL客戶端認證請求。若是須要提供密鑰,主程序負責顯示UI界面。 
  42.  * 有三個響應方法:proceed(), cancel() 和 ignore()。 
  43.  * 若是調用proceed()和cancel(),webview將會記住response, 
  44.  * 對相同的host和port地址再也不調用onReceivedClientCertRequest方法。 
  45.  * 若是調用ignore()方法,webview則不會記住response。該方法在UI線程中執行, 
  46.  * 在回調期間,鏈接被掛起。默認cancel(),即無客戶端認證 
  47.  */  
  48. onReceivedClientCertRequest(WebView view, ClientCertRequest request)<span style="color:#006600;">  
  49. </span>  

2、其它事件處理

上面講了有關WebViewClient的用法,但其中還有一些小問題是WebViewClient沒法解決的,好比返回按鍵、滾動事件監聽等,下面咱們就這些問題來跟你們作下探討

一、返回按鍵

若是用webview點連接看了不少頁之後,若是不作任何處理,點擊系統「Back」鍵,整個瀏覽器會調用finish()而結束自身,若是但願瀏覽的網頁回退而不是退出瀏覽器,須要在當前Activity中處理並消費掉該Back事件。 覆蓋Activity類的onKeyDown(int keyCoder,KeyEvent event)方法。
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.         mWebView.setWebViewClient(new WebViewClient());  
  15.   
  16.         mWebView.loadUrl("http://blog.csdn.net/harvic880925/");  
  17.     }  
  18.   
  19.     @Override  
  20.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  21.          //改寫物理返回鍵的邏輯  
  22.         if(keyCode==KeyEvent.KEYCODE_BACK) {  
  23.             if(mWebView.canGoBack()) {  
  24.                 mWebView.goBack();//返回上一頁面   
  25.                 return true;  
  26.             } else {  
  27.                 System.exit(0);//退出程序   
  28.             }  
  29.         }  
  30.         return super.onKeyDown(keyCode, event);  
  31.     }  
  32. }  
在未重寫onKeyDown前的效果圖:點擊回退按鈕,整個Activity就銷燬了

 

重寫onKeyDown後的效果圖:
sql

可見在重寫onKeyDown後,點擊回退按鈕時,就會回退到WebView的上一個頁面。

二、滾動事件監聽

咱們都知道監聽滾動事件通常都是設置setOnScrollChangedListener,惋惜的是 WebView並無給咱們提供這樣的方法,可是咱們能夠重寫WebView,覆蓋裏面的一個方法: protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){} 而後再對外提供一個接口,示例代碼以下:

 

 

[java]  view plain  copy
  1. public class MyWebView extends WebView {  
  2.   
  3.     private OnScrollChangedCallback mOnScrollChangedCallback;  
  4.   
  5.     public MyWebView(Context context) {  
  6.         super(context);  
  7.     }  
  8.   
  9.     public MyWebView(Context context, AttributeSet attrs) {  
  10.         super(context, attrs);  
  11.     }  
  12.   
  13.     public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {  
  14.         super(context, attrs, defStyleAttr);  
  15.     }  
  16.   
  17.     @Override  
  18.     protected void onScrollChanged(int l, int t, int oldl, int oldt) {  
  19.         super.onScrollChanged(l, t, oldl, oldt);  
  20.         if (mOnScrollChangedCallback != null) {  
  21.             mOnScrollChangedCallback.onScroll(l,t,oldl,oldt);  
  22.         }  
  23.     }  
  24.   
  25.     public OnScrollChangedCallback getOnScrollChangedCallback() {  
  26.         return mOnScrollChangedCallback;  
  27.     }  
  28.   
  29.     public void setOnScrollChangedCallback(  
  30.             final OnScrollChangedCallback onScrollChangedCallback) {  
  31.         mOnScrollChangedCallback = onScrollChangedCallback;  
  32.     }  
  33.   
  34.     public static interface OnScrollChangedCallback {  
  35.         public void onScroll(int left,int top ,int oldLeft,int oldTop);  
  36.     }  
  37. }  
這段代碼難度不大,就再也不細講了。

三、如何強制使用外部瀏覽器打開網頁

若是不想在 webview 中顯示網頁,而是直接跳轉到瀏覽器的話,能夠像下邊那樣調用。
[java]  view plain  copy
  1. Uri uri = Uri.parse("http://www.example.com");   
  2. Intent intent = new Intent(Intent.ACTION_VIEW, uri);   
  3. startActivity(intent);  
這裏是使用隱式Intent的方式來啓用外部應用,有關隱式Intent的知識,能夠參考: 
《intent詳解(一)》 
《intent詳解(二)》

好了,這篇文章就到這裏了,下篇文章給你們繼續講解有關WebView的知識。

 

若是本文有幫到你,記得加關注哦

源碼下載地址:http://download.csdn.net/detail/harvic880925/9534186

請你們尊重原創者版權,轉載請標明出處:http://blog.csdn.net/harvic880925/article/details/51523983 謝謝

 

若是你喜歡個人文章,那麼你將會更喜歡個人微信公衆號,將按期推送博主最新文章與收集乾貨分享給你們(一週一次)

 

 
24
0
 
 
 

 

 
查看評論
12樓  bruce_lv 4天前 12:19發表  [回覆]
[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  4.         if (url.contains("csdn")){  
  5.             view.loadUrl("baidu");  
  6.         }  
  7.         return false;  
  8.     }  
  9. }    

此時除了請求baidu還會請求CSDN嗎?
11樓  moyisiha 2017-06-23 10:11發表  [回覆]
請問:
假如JS中返回按鈕直接調用了系統window.histroy(-1)
這個時候,webview能監聽到這個信號嗎
10樓  貝澪 2017-02-24 09:47發表  [回覆]
真的很是詳細,感謝幫助!
9樓  xlx602158474 2016-12-27 17:45發表  [回覆]
樓主上面講到當加載https的網址時,出現SSL錯誤時,若是想要忽略掉該錯誤,要調用handler.process()方法,並必定要刪除掉super.onReceivedSslError(view, handler, error)方法,但我沒有刪除那個方法,網頁也加載出來了,這是爲何???。注:網址是https的,而且必須調用handler.process()才能加載出網頁。
8樓  Jugg_VS_Spe_細節多到爆炸 2016-12-14 16:45發表  [回覆]
厲害厲害,感謝幫助!
7樓  wangyao20 2016-12-14 16:40發表  [回覆]
樓主,你好 若是我想在loadurl再接收廣播怎麼辦,如今cordovaActivity接收不了廣播,好比藍牙按鍵廣播
6樓  xc87607536 2016-09-27 15:36發表  [回覆]
我是來看博主的本地圖片的
5樓  zyj_9327 2016-08-19 17:28發表  [回覆]
灰常感謝樓主的分享,很清晰很條理!學習了!
樓主好棒!!!!
4樓  xiaozilong168 2016-07-22 19:21發表  [回覆]
大神請教
WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);  
return response;

若是我想用一個URL網址替換本來要將要打開的URL網址怎麼辦呢?
Re:  Look19 2016-12-06 10:39發表  [回覆]
回覆xiaozilong168:羣主講的不是有攔截的,直接在攔截裏面操做就能夠了~
3樓  xiaozilong168 2016-07-22 19:20發表  [回覆]
大神,求教。。
WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);  
return response;

若是我是想用一個網絡上的圖片或網頁地址替換原有URL怎麼作呢?而不是從本地讀一個文件出來替換。
2樓  Hankins_Pan 2016-06-07 13:18發表  [回覆]
博主總結的很是細緻,條例清晰,結構規整,演示明瞭。學習了!感謝分享!
1樓  哆啦miss夢 2016-05-31 22:40發表  [回覆]
大神,能夠換成Markdown編輯了,看起感受舒服一些
 
* 以上用戶言論只表明其我的觀點,不表明CSDN網站的觀點或立場
 
 
 
 
    我的資料
 
 
1  1
    • 訪問:3855788次
    • 積分:24247
    • 等級: 
    • 排名:第256名
    • 原創:231篇
    • 轉載:35篇
    • 譯文:0篇
    • 評論:2581條
    個人新浪微博
    交流羣來啦
新建了一個交流羣,你們能夠加入
       

QQ羣號一(已滿):304235209
QQ羣號二:554244703
       


博主須要你!!!
       


個人微信公衆號
       

      關注博主最新動態和乾貨分享,一週一次 
       

      下面是我作IT技術面試輔導的公衆號,旨在爲你們提供技術面試相關的資料與支持 

       
    博客專欄
《Animation動畫詳解》

文章:13篇

閱讀:236559
    文章存檔
    最新評論
 
 
相關文章
相關標籤/搜索