在上一篇中我們說了WebView的基本使用安卓開發(fā)之WebView的使用(1),里面提到了WebViewClient和WebChromeClient。
下面我們來探究一番WebViewClient和WebChromeClient
Let's Go
先了解一下概念
Android WebView做為承載網(wǎng)頁的載體控件,他在網(wǎng)頁顯示的過程中會產(chǎn)生一些事件,并回調(diào)給我們的應用程序,以便我們在網(wǎng)頁加載過程中做應用程序想處理的事情。比如說客戶端需要顯示網(wǎng)頁加載的進度、網(wǎng)頁加載發(fā)生錯誤等等事件。
WebView提供兩個事件回調(diào)類給應用層,分別為WebViewClient和WebChromeClient。我們可以繼承這兩個類,接受相應事件處理。
WebViewClient: 主要提供網(wǎng)頁加載各個階段的通知,比如網(wǎng)頁開始加載onPageStarted,網(wǎng)頁結(jié)束加載onPageFinished等。
WebChromeClient: 主要提供網(wǎng)頁加載過程中提供的數(shù)據(jù)內(nèi)容,比如返回網(wǎng)頁的title,favicon等。
下面先從WebViewClient開始說起
WebViewClient的基本使用
WebViewClient的基本使用
創(chuàng)建WebViewClient實例并設置到WebView對象中,具體代碼參考如下:
class MyAndroidWebViewClient extends WebViewClient {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO
}
@Override
public void onPageFinished(WebView view, String url) {
}
}
webview.setWebViewClient(new MyAndroidWebViewClient ());
來看看API
public boolean shouldOverrideUrlLoading(WebView view, String url)
當加載的網(wǎng)頁需要重定向的時候就會回調(diào)這個函數(shù)告知我們應用程序是否需要接管控制網(wǎng)頁加載,如果應用程序接管,并且return true意味著主程序接管網(wǎng)頁加載,如果返回false讓webview自己處理。
參數(shù)說明:
@param view 接收WebViewClient的那個實例
@param url 即將要被加載的url
@return true 當前應用程序要自己處理這個url, 返回false則不處理。
Tips:
(1) 當請求的方式是"POST"方式時這個回調(diào)是不會通知的。
(2) 當我們訪問的地址需要我們應用程序自己處理的時候,可以在這里截獲,比如我們發(fā)現(xiàn)跳轉(zhuǎn)到的是一個market的鏈接,那么我們可以直接跳轉(zhuǎn)到應用市場,或者其他app。public void onPageStarted(WebView view, String url, Bitmap favicon)
當內(nèi)核開始加載訪問的url時,會通知應用程序,對每個main frame這個函數(shù)只會被調(diào)用一次,頁面包含iframe 或者framesets 不會另外調(diào)用一次onPageStarted,當網(wǎng)頁內(nèi)內(nèi)嵌的frame 發(fā)生改變時也不會調(diào)用onPageStarted。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param url 即將要被加載的url
@param favicon 如果這個favicon已經(jīng)存儲在本地數(shù)據(jù)庫中,則會返回這個網(wǎng)頁的favicon,否則返回為null。
Tips:
(1) iframe 可能不少人不知道什么含義,這里我解釋下,iframe我們加載的一張,下面有很多鏈接,我們隨便點擊一個鏈接是即當前host的一個iframe.
(2) 有個問題可能是開發(fā)者困惑的,onPageStarted和shouldOverrideUrlLoading 在網(wǎng)頁加載過程中這兩個函數(shù)到底哪個先被調(diào)用。當我們通過loadUrl的方式重新加載一個網(wǎng)址時候,這時候會先調(diào)用onPageStarted再調(diào)用shouldOverrideUrlLoading,當我們在打開的這個網(wǎng)址點擊一個link,這時候會先調(diào)用shouldOverrideUrlLoading再調(diào)用onPageStarted。
不過shouldOverrideUrlLoading不一定每次都被調(diào)用,只有需要的時候才會被調(diào)用。public void onPageFinished(WebView view, String url)
當內(nèi)核加載完當前頁面時會通知我們的應用程序,這個函數(shù)只有在main frame情況下才會被調(diào)用,當調(diào)用這個函數(shù)之后,渲染的圖片不會被更新,如果需要獲得新圖片的通知可以使用@link WebView.PictureListener#onNewPicture。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param url 即將要被加載的urlpublic void onLoadResource(WebView view, String url)
通知應用程序WebView即將加載url 制定的資源
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param url 即將加載的url 資源public WebResourceResponse shouldInterceptRequest(WebView view, String url)
通知應用程序內(nèi)核即將加載url制定的資源,應用程序可以返回本地的資源提供給內(nèi)核,若本地處理返回數(shù)據(jù),內(nèi)核不從網(wǎng)絡上獲取數(shù)據(jù)。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param url raw url 制定的資源
@return 返回WebResourceResponse包含數(shù)據(jù)對象,或者返回null
Tips
這個回調(diào)并不一定在UI線程執(zhí)行,所以我們需要注意在這里操作View或者私有數(shù)據(jù)相關的動作。
如果我們需要改變網(wǎng)頁的背景,或者需要實現(xiàn)網(wǎng)頁頁面顏色定制化的需求,可以在這個回調(diào)時機處理。public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
當瀏覽器訪問制定的網(wǎng)址發(fā)生錯誤時會通知我們應用程序,比如網(wǎng)絡錯誤。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param errorCode 錯誤號可以在WebViewClient.ERROR 里面找到對應的錯誤名稱。
@param description 描述錯誤的信息
@param failingUrl 當前訪問失敗的url,注意并不一定是我們主url
Tips
在onReceiveError我們可以自定義網(wǎng)頁的錯誤頁面。public void onFormResubmission(WebView view, Message dontResend, Message resend)
如果瀏覽器需要重新發(fā)送POST請求,可以通過這個時機來處理。默認是不重新發(fā)送數(shù)據(jù)。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param dontResent 當瀏覽器不需要重新發(fā)送數(shù)據(jù)時,可以使用這個參數(shù)。
@param resent 當瀏覽器需要重新發(fā)送數(shù)據(jù)時, 可以使用這個參數(shù)。public void doUpdateVisitedHistory(WebView view, String url, boolean isReload)
通知應用程序可以將當前的url存儲在數(shù)據(jù)庫中,意味著當前的訪問url已經(jīng)生效并被記錄在內(nèi)核當中。
這個函數(shù)在網(wǎng)頁加載過程中只會被調(diào)用一次。注意網(wǎng)頁前進后退并不會回調(diào)這個函數(shù)。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param url 當前正在訪問的url
@ param isReload 如果是true 這個是正在被reload的urlpublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
當網(wǎng)頁加載資源過程中發(fā)現(xiàn)SSL錯誤會調(diào)用此方法。我們應用程序必須做出響應,是取消請求handler.cancel(),還是繼續(xù)請求handler.proceed();內(nèi)核的默認行為是handler.cancel();
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param handler 處理用戶請求的對象。
@param error SSL錯誤對象
Tips
內(nèi)核會記住本次選擇,如果下次還有相同的錯誤,內(nèi)核會直接執(zhí)行之前選擇的結(jié)果。public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
通知應用程序WebView接收到了一個Http auth的請求,應用程序可以使用supplied 設置webview的響應請求。默認行為是cancel 本次請求。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,
前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param handler 用來響應WebView請求的對象
@param host 請求認證的host
@param realm 認真請求所在的域public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
提供應用程序同步一個處理按鍵事件的機會,菜單快捷鍵需要被過濾掉。如果返回true,webview不處理該事件,如果返回false, webview會一直處理這個事件,因此在view 鏈上沒有一個父類可以響應到這個事件。默認行為是return false;
參數(shù)說明:
@param view 接收WebViewClient的那個實例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview。
@param event 鍵盤事件名
@return 如果返回true,應用程序處理該時間,返回false 交有webview處理。public void onScaleChanged(WebView view, float oldScale, float newScale)
通知應用程序webview 要被scale。應用程序可以處理改事件,比如調(diào)整適配屏幕。public void onReceivedLoginRequest(WebView view, String realm, String account, String args)
通知應用程序有個自動登錄的帳號過程
參數(shù)說明:
@param view 請求登陸的webview
@param realm 賬戶的域名,用來查找賬戶。
@param account 一個可選的賬戶,如果是null 需要和本地的賬戶進行check, 如果是一個可用的賬戶,則提供登錄。
@param args 驗證制定參數(shù)的登錄用戶
WebChromeClient基本使用
API
public void onProgressChanged(WebView view, int newProgress)
通知應用程序當前網(wǎng)頁加載的進度。
參數(shù)說明:
@param view WebView
@newProgress 進度public void onReceivedTitle(WebView view, String title)
當document 的title變化時,會通知應用程序
參數(shù)說明:
@param view WebView
@param title document的title
Tips
這個函數(shù)調(diào)用時機不確定,有可能很早,有可能很晚,取決于網(wǎng)頁把title設置在什么位置,
大多數(shù)網(wǎng)頁一般把title設置到頁面的前面,因此很多情況會比較早回調(diào)到這個函數(shù)。public void onReceivedIcon(WebView view, Bitmap icon)
當前頁面有個新的favicon時候,會回調(diào)這個函數(shù)。
參數(shù)說明:
@param view WebView
@param icon 當前頁面的faviconpublic void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)
通知應用程序 apple-touch-icon的 url
參數(shù)說明:
@param view WebView
@param url apple-touch-icon 的服務端地址
@param precomposed 如果precomposed 是true 則touch-icon是預先創(chuàng)建的
Tips
如果應用程序需要這個icon的話, 可以通過這個url獲取得到 icon。public void onShowCustomView(View view, CustomViewCallback callback)
view,主要是用在視頻全屏HTML5 Video support。
參數(shù)說明:
@param view 即將要顯示的view
@param callback 當view 需要dismiss 則使用這個對象進行回調(diào)通知。public void onHideCustomView()
隱藏view,如退出視頻通知public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
請求創(chuàng)建一個新的窗口,如果我們應用程序接管這個請求,必須返回true,并且創(chuàng)建一個新的webview來承載主窗口。如果應用程序不處理,則需要返回false,默認行為和返回false表現(xiàn)一樣。
參數(shù)說明:
@param view 請求創(chuàng)建新窗口的webview
@param isUserGesture 如果是true,則說明是來自用戶收拾操作行為,比如用戶點擊鏈接
@param isDialog true 請求創(chuàng)建的新窗口必須是個dialog,而不是全屏的窗口。
@param resultMsg 當webview創(chuàng)建時需要發(fā)送一個消息。WebView.WebViewTransport.setWebView(WebView)
Tips 具體例子如下:
private void createWindow(final Message msg){
WebView.WebViewTransport transport = (WebView.WebViewTransport) msg.obj;
final Tab newTab = mWebViewController.openTab(null, Tab.this, true, true);
transport.setWebView(newTab.getWebView());
msg.sendToTarget();
}
public void onRequestFocus(WebView view)
webview請求得到focus,發(fā)生這個主要是當前webview不是前臺狀態(tài),是后臺webview。public void onCloseWindow(WebView window)
通知應用程序從關閉傳遞過來的webview并從view tree中remove。public boolean onJsAlert(WebView view, String url, String message, JsResult result)
通知應用程序顯示javascript alert對話框,如果應用程序返回true內(nèi)核認為應用程序處理這個消息,返回false,內(nèi)核自己處理。
參數(shù)說明:
@param view webview。
@param url 當前請求彈出javascript 對話框webview 加載的url地址。
@param message 彈出的內(nèi)容信息
@result 用來響應用戶的處理。
Tips
如果我們應用接管處理, 則必須給出result的結(jié)果,result.cancel,result.comfirm必須調(diào)用其中之后,否則內(nèi)核會hang住。public boolean onJsConfirm(WebView view, String url, String message,JsResult result)
通知應用程序提供confirm 對話框。 參數(shù)說明同上onJsAlertpublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
通知應用程序顯示一個prompt對話框。
Tips
必須調(diào)用result.confirm 方法如果應用程序接管這個方法。public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result)
通知應用程序顯示一個對話框,讓用戶選擇是否離開當前頁面,這個回調(diào)是javascript中的onbeforeunload事件,如果客戶端返回true,內(nèi)核會認為客戶端提供對話框。默認行為是return false。
參數(shù)說明和之前介紹的onJsAlert()相同。public void onExceededDatabaseQuota(String url, String databaseIdentifier, long quota, long estimatedDatabaseSize, long totalQuota, WebStorage.QuotaUpdater quotaUpdater)
通知應用程序webview內(nèi)核web sql 數(shù)據(jù)庫超出配額,請求是否擴大數(shù)據(jù)庫磁盤配額。默認行為是不會增加數(shù)據(jù)庫配額。
參數(shù)說明:
@param url 觸發(fā)這個數(shù)據(jù)庫配額的url地址
@param databaseIdentifier 指示出現(xiàn)數(shù)據(jù)庫超過配額的標識。
@param quota 原始數(shù)據(jù)庫配額的大小,是字節(jié)單位bytes
@param estimatedDatabaseSize 到達底線的數(shù)據(jù)大小 bytes
@param totalQuota 總的數(shù)據(jù)庫配額大小 bytes
@param quotaUpdater 更新數(shù)據(jù)庫配額的對象,可以使用 quotaUpdater.updateQuota(newQuota);配置新的數(shù)據(jù)庫配額大小。public void onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)
通知應用程序內(nèi)核已經(jīng)到達最大的appcache。appcache是HTML5針對offline的一個數(shù)據(jù)處理標準。public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback)
當前頁面請求是否允許進行定位。
GeolocationPermissions.Callback的方法:
1.public void invoke(String origin, boolean allow, boolean retain);
參數(shù)說明:
@param origin 權(quán)限設置的源地址
@param allow 是否允許定位
@retain 當前的選擇是否讓內(nèi)核記住。
2.public void onGeolocationPermissionsHidePrompt()public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture)
這個回調(diào)是私有回調(diào), 當頁面需要請求打開系統(tǒng)的文件選擇器,則會回調(diào)這個方法,比如我們需要上傳圖片,請求拍照,郵件的附件上傳等等操作。如果不實現(xiàn)這個私有API,則上面的請求都將不會執(zhí)行。