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