WebView使用解析(二)之WebViewClient/WebChromeClient
WebViewClient—–在影響View的事件到來時,會通過WebViewClient中的方法回撥通知使用者。
WebChromeClient—–當影響瀏覽器的事件到來時,就會通過WebChromeClient中的方法回撥通知用法。
通過上面的對比,我們發現WebViewClient和WebChromeClient都是針對不同事件的回撥,而google將這些回撥進行分類集合,就產生了WebViewClient、WebChromeClient這兩個大類,其中管理著針對不同型別的回撥而已。
WebViewClient
WebViewClient中函式概述:
/**
* 在開始載入網頁時會回撥
*/
public void onPageStarted(WebView view, String url, Bitmap favicon)
/**
* 在結束載入網頁時會回撥
*/
public void onPageFinished(WebView view, String url)
/**
* 攔截 url 跳轉,在裡邊新增點選連結跳轉或者操作
*/
public boolean shouldOverrideUrlLoading(WebView view, String url)
/**
* 載入錯誤的時候會回撥,在其中可做錯誤處理,比如再請求載入一次,或者提示404的錯誤頁面
*/
public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)
/**
* 當接收到https錯誤時,會回撥此函式,在其中可以做錯誤處理
*/
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)
/**
* 在每一次請求資源時,都會通過這個函式來回調
*/
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return null;
}
我們一個個來看:
1. WebViewClient之onPageStarted與onPageFinished
onPageStarted:通知主程式頁面當前開始載入。
onPageFinished:通知主程式頁面載入結束。
舉個例子:開始載入時顯示載入圓圈,結束載入時隱藏載入圓圈。
public class MainActivity extends Activity {
private WebView mWebView;
private ProgressDialog mProgressDialog;
private String TAG = "watson";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView)findViewById(R.id.webview);
mProgressDialog = new ProgressDialog(this);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("http://blog.csdn.net/huaxun66");
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
mWebView.loadUrl(url);
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
mProgressDialog.show();
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mProgressDialog.hide();
}
});
}
}
從圖中可以看出,在載入頁面的時候會顯示圓形載入框,在載入成功以後會隱藏載入框。
2. WebViewClient之shouldOverrideUrlLoading
(1)如何在WebView中載入線上網址
上篇文章也說過,如果要在WebView中載入線上網址,必須重寫WebViewClient,其實給webview設定一個空的WebViewClient物件即可,沒必要重寫WebViewClient的方法。使用它的預設回撥就可以實現在WebView中載入線上URL了:
mWebView.setWebViewClient(new WebViewClient());
(2)shouldOverrideUrlLoading用途
由於每次超連結在載入前都會先走shouldOverrideUrlLoading回撥,所以我們如果想攔截某個URL,將其轉換成其它URL可以在這裡做。
比如,我們攔截所有包含“blog.csdn.net”的地址,將其替換成”www.baidu.com”:
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("blog.csdn.net")){
view.loadUrl("http://www.baidu.com");
}
return false;
}
});
效果圖如下:
這裡需要非常注意的是:返回值是boolean型別,表示是否遮蔽WebView繼續載入URL的預設行為。因為這個函式是WebView載入URL前回調的,所以如果我們return true,則WebView接下來就不會再載入這個URL了。如果我們return false,則系統就認為上層沒有做處理,接下來還是會繼續載入這個URL的。WebViewClient預設就是return false的。
一般建議大家return false,我們只關心我們關心的攔截內容,對於不攔截的內容,讓系統自己來處理即可。就像我們上面的程式碼。
3. WebViewClient之onReceivedError
onReceivedError的完整宣告如下:
public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)
載入錯誤的時候會產生這個回撥,在其中可做錯誤處理,比如我們可以載入一個錯誤提示頁面
這裡有四個引數:
- WebView view:當前的WebView例項
- int errorCode:錯誤碼
- String description:錯誤描述
- String failingUrl:當前出錯的URL
我們可以先寫一個錯誤提示的本地頁面:(error.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="h">出錯了……</h1>
</body>
</html>
然後在載入返回錯誤時,重新載入錯誤頁面:
mWebView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
mWebView.loadUrl("file:///android_asset/error.html");
}
});
最後讓webview載入一個錯誤的URL。
4.WebViewClient之onReceivedSslError
我們知道HTTPS協議是通過SSL來通訊的,所以當使用HTTPS通訊的網址(以https://開頭的網站)出現錯誤時,就會通過onReceivedSslError回撥通知過來,它的函式宣告為:
/**
* 當接收到https錯誤時,會回撥此函式,在其中可以做錯誤處理
*/
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錯誤的基本所有資訊
預設載入SSL出錯的網站——出現空白頁面
12306是通過Https協議來傳輸的,但是它的SSL證書不是CA頒發的,不被我們APP認可,所以我們就以12306網站為例:
public class MainActivity extends Activity {
private WebView mWebView;
private String TAG = "watson";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView)findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("https://www.12306.cn/");
mWebView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error);
}
});
}
}
在這裡僅僅重寫onReceivedSslError,並呼叫super.onReceivedSslError(view, handler, error);來呼叫預設的處理方式。發現頁面顯示空白。
我們修改一下程式碼:
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
// 一定要註釋掉!
// super.onReceivedSslError(view, handler, error);
handler.proceed();
}
這裡做了兩個改變:
第一:註釋掉super.onReceivedSslError(view, handler, error);,取消系統的預設行為,我們看原始碼,可以發現WebViewClient中onReceivedSslError的預設實現是handler.cancel(); 即取消繼續載入。
第二:呼叫handler.proceed();來忽略錯誤繼續載入頁面。
所以此時的效果圖為:
對於onReceivedSslError結論:
1.當出現SSL錯誤時,WebView預設是取消載入當前頁面,只有去掉onReceivedSslError的預設操作,然後新增SslErrorHandler.proceed()才能繼續加載出錯頁面
2.當HTTPS傳輸出現SSL錯誤時,錯誤會只通過onReceivedSslError回撥傳過來,不會執行onReceivedError
5. WebViewClient之shouldInterceptRequest
在每一次請求資源時,都會通過這個函式來回調,比如超連結、JS檔案、CSS檔案、圖片等,也就是說瀏覽器中每一次請求資源時,都會回調回來,無論任何資源!但是必須注意的是shouldInterceptRequest函式是在非UI執行緒中執行的,在其中不能直接做UI操作,如果需要做UI操作,則需要利用Handler來實現,該函式宣告如下:
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return null;
}
該函式會在請求資源前呼叫,我們可以通過返回WebResourceResponse的處理結果來讓WebView直接使用我們的處理結果。如果我們不想處理,則直接返回null,系統會繼續載入該資源。
利用這個特性,我們可以解決一個需求:假如網頁中需要載入本地的圖片,我們就可以通過攔截shouldInterceptRequest,並返回結果即可 。
比如下面的一段HTML程式碼中,img欄位載入圖片的地址是:http://localhost/android.png,這是我自定義的一個網址,在Android中,當發現要載入這個地址的資源時,我們將它換成本地的圖片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="h">WebView使用解析</h1>
<img src="http://localhost/android.png"/>
</body>
</html>
public class MainActivity extends Activity {
private WebView mWebView;
private String TAG = "watson";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
try {
if (url.equals("http://localhost/android.png")) {
AssetFileDescriptor fileDescriptor = getAssets().openFd("qqq.jpg");
InputStream stream = fileDescriptor.createInputStream();
WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);
return response;
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return super.shouldInterceptRequest(view, url);
}
});
mWebView.loadUrl("file:///android_asset/web.html");
}
}
這裡程式碼比較容易理解,當發現當前載入資源的url是我們自定義的http://localhost/android.jpg時,就直接將本地的圖片qqq.jpg作為結果返回。
6. WebViewClient之其餘函式
/**
* 在載入頁面資源時會呼叫,每一個資源(比如圖片)的載入都會呼叫一次
*/
public void onLoadResource(WebView view, String url)
/**
* (WebView發生改變時呼叫)
* 可以參考http://www.it1352.com/191180.html的用法
*/
public void onScaleChanged(WebView view, float oldScale, float newScale)
/**
* 重寫此方法才能夠處理在瀏覽器中的按鍵事件。
* 是否讓主程式同步處理Key Event事件,如過濾選單快捷鍵的Key Event事件。
* 如果返回true,WebView不會處理Key Event,
* 如果返回false,Key Event總是由WebView處理。預設:false
*/
public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
/**
* 是否重發POST請求資料,預設不重發。
*/
onFormResubmission(WebView view, Message dontResend, Message resend)
/**
* 更新訪問歷史
*/
doUpdateVisitedHistory(WebView view, String url, boolean isReload)
/**
* 通知主程式輸入事件不是由WebView呼叫。是否讓主程式處理WebView未處理的Input Event。
* 除了系統按鍵,WebView總是消耗掉輸入事件或shouldOverrideKeyEvent返回true。
* 該方法由event 分發非同步呼叫。注意:如果事件為MotionEvent,則事件的生命週期只存在方法呼叫過程中,
* 如果WebViewClient想要使用這個Event,則需要複製Event物件。
*/
onUnhandledInputEvent(WebView view, InputEvent event)
/**
* 通知主程式執行了自動登入請求。
*/
onReceivedLoginRequest(WebView view, String realm, String account, String args)
/**
* 通知主程式:WebView接收HTTP認證請求,主程式可以使用HttpAuthHandler為請求設定WebView響應。預設取消請求。
*/
onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
/**
* 通知主程式處理SSL客戶端認證請求。如果需要提供金鑰,主程式負責顯示UI介面。
* 有三個響應方法:proceed(), cancel() 和 ignore()。
* 如果呼叫proceed()和cancel(),webview將會記住response,
* 對相同的host和port地址不再呼叫onReceivedClientCertRequest方法。
* 如果呼叫ignore()方法,webview則不會記住response。該方法在UI執行緒中執行,
* 在回撥期間,連線被掛起。預設cancel(),即無客戶端認證
*/
onReceivedClientCertRequest(WebView view, ClientCertRequest request)
WebChromeClient
WebChromeClient的常用函式:
/**
* 當網頁呼叫alert()來彈出alert彈出框前回調,用以攔截alert()函式
*/
public boolean onJsAlert(WebView view, String url, String message,JsResult result)
/**
* 當網頁呼叫confirm()來彈出confirm彈出框前回調,用以攔截confirm()函式
*/
public boolean onJsConfirm(WebView view, String url, String message,JsResult result)
/**
* 當網頁呼叫prompt()來彈出prompt彈出框前回調,用以攔截prompt()函式
*/
public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result)
/**
* 列印 console 資訊
*/
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
/**
* 通知程式當前頁面載入進度
*/
public void onProgressChanged(WebView view, int newProgress)
1. WebChromeClient之onJsAlert、onJsConfirm、onJsPrompt
我們把這三個函式一起看,因為他們都是為了處理彈出框。
(1)、為何JS中的alert()、confirm()、prompt()無效
首先,我們來舉個例子,在網頁中加上按鈕,在點選時分別呼叫alert()、confirm()、prompt()來彈出不同的對話方塊 。
web.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="h">WebView使用解析</h1>
<button onclick="confirm('confirm文字')">confirm</button>
<button onclick="alert('alert文字')">alert</button>
<button onclick="prompt('prompt文字')">prompt</button>
</body>
</html>
JAVA
public class MainActivity extends Activity {
private WebView mWebView;
private String TAG = "watson";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUrl("file:///android_asset/web.html");
}
}
從效果圖中,雖然啟用了JavaScript但是在網頁中的confrim()、alert()、prompt()卻是沒有效果!
我們只需要在程式中加上一句話就可以實現confrim()、alert()、prompt()的彈出效果了 。
mWebView.setWebChromeClient(new WebChromeClient());
(2)使用onJsAlert攔截alert()函式概述
複寫onJsAlert函式:
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Toast.makeText(MainActivity.this,"onJsAlert message="+message,Toast.LENGTH_SHORT).show();
result.confirm();
return true;
}
});
這三句話,句句非常重要:
第一句:
Toast.makeText(MainActivity.this,"onJsAlert message="+message,Toast.LENGTH_SHORT).show();
表示我們攔截html中alert函式之後,做我們自己的操作,這裡是彈出一行toast。
第二句:
result.confirm();
這句話非常重要,它表示向WebView通知操作結果,JsResult有兩個函式:JsResult.confirm()和JsResult.cancel(),JsResult.confirm()相當於點選了彈出框的確定按鈕,JsResult.cancel()則相當於點選了彈出框的取消按鈕。
如果沒有使用JsResult來告訴WebView處理結果,則WebView就會認為這個彈出框還一直彈在那裡,你再點選alert按鈕,將會無效;
第三句:
return true;
表示告訴WebView我們已經攔截了alert()函式,不需要再彈出網頁中的alert彈出框了,如果我們return false,那麼WebView就會認為我們沒有攔截alert()函式,會繼續彈出alert對話方塊。
有關confrim()和prompt()的攔截,我們就不再講了,與攔截alert()一樣!
2、WebChromeClient之onConsoleMessage
當html中呼叫console相關輸出的時候,就會通過onConsoleMessage進行通知
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
引數意義:
- ConsoleMessage consoleMessage:儲存著當前訊息的型別和訊息內容返回值:如果返回true時,就表示攔截了console輸出,系統就不再通過console輸出出來了,如果返回false則表示沒有攔截console輸出,呼叫系統預設處理。
我們來看下正常情況下,console輸出的內容及用法
先來看html內容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="h">WebView使用解析</h1>
<button onclick="log()">log</button>
</body>
<script type="text/javascript">
function log(){
console.log("console.log");
console.warn("warnning");
console.error("error");
}
</script>
</html>
JAVA程式碼:
public class MainActivity extends Activity {
private WebView mWebView;
private String TAG = "watson";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUrl("file:///android_asset/web.html");
}
}
除了alert,prompt,confirm以外,其它時候都不需要強制設定WebChromeClient 。
當點選log按鈕時,會呼叫console的函式把log輸出出來
logcat中可以看到如下日誌:
下面我們就重寫WebChromeClient的onConsoleMessage方法,把console訊息攔截掉,然後把訊息利用toast彈出來:
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Toast.makeText(MainActivity.this,consoleMessage.message(),Toast.LENGTH_SHORT).show();
return true;
}
});
效果圖如下:
由於我們return true,訊息攔截成功,控制檯將不會再看到我們的訊息日誌了。
3、WebChromeClient之onProgressChanged
表示當前頁面的載入速度,函式宣告如下:
public void onProgressChanged(WebView view, int newProgress)
- WebView view:當前WebView例項
- int newProgress:當前的載入進度,值從0到100
public void onProgressChanged(WebView view, int newProgress) {
Log.e(TAG,"progress:"+newProgress);
super.onProgressChanged(view, newProgress);
}
大家一定要注意,底層實現時,是利用handler來定時輪循當前進度的,每隔一定時間查詢一次,所以每次拿到的進度資料是不一樣的,也就是說如果頁面較簡單,可能會直接返回100,而跳過中間的各個資料。也就是說,除了100,其它任何一個數值不是一定返回的,所以大家如果要用到進度除了數值100可以用等號來判斷,其它一定要用大於號或小於號,如果用了等號,可能永遠也不會執行到!
4、WebChromeClient之其它函式
/*
* 通知頁面標題變化
*/
nReceivedTitle(WebView view, String title)
/*
* 通知當前頁面網站新圖示
*/
onReceivedIcon(WebView view, Bitmap icon)
/*
* 通知主程式圖示按鈕URL
*/
onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)
/*
* 通知主程式當前頁面將要顯示指定方向的View,該方法用來全屏播放視訊。
*/
public interface CustomViewCallback {
// 通知當前頁面自定義的View被關閉
public void onCustomViewHidden();
}
onShowCustomView(View view, CustomViewCallback callback)
/*
* 與onShowCustomView對應,通知主程式當前頁面將要關閉Custom View
*/
onHideCustomView()
/**
* 請求主程式建立一個新的Window,如果主程式接收請求,返回true並建立一個新的WebView來裝載Window,然後新增到View中,傳送帶有建立的WebView作為引數的resultMsg的給Target。如果主程式拒絕接收請求,則方法返回false。預設不做任何處理,返回false
*/
onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
/*
* 顯示當前WebView,為當前WebView獲取焦點。
*/
onRequestFocus(WebView view)
/*
* 通知主程式關閉WebView,並從View中移除,WebCore停止任何的進行中的載入和JS功能。
*/
onCloseWindow(WebView window)
/**
* 告訴客戶端顯示離開當前頁面的導航提示框。如果返回true,由客戶端處理確認提示框,呼叫合適的JsResult方法。如果返回false,則返回預設值true給javascript接受離開當前頁面的導航。預設:false。JsResult設定false,當前頁面取消導航提示,否則離開當前頁面。
*/
onJsBeforeUnload(WebView view, String url, String message, JsResult result)
/**
*通知主程式web內容嘗試使用定位API,但是沒有相關的許可權。主程式需要呼叫呼叫指定的定位許可權申請的回撥。更多說明檢視GeolocationPermissions相關API。
*/
onGeolocationPermissionsShowPrompt(String origin,GeolocationPermissions.Callback callback)
/*
* 通知程式有定位許可權請求。如果onGeolocationPermissionsShowPrompt許可權申請操作被取消,則隱藏相關的UI介面。
*/
onGeolocationPermissionsHidePrompt()
/**
*通知主程式web內容嘗試申請指定資源的許可權(許可權沒有授權或已拒絕),主程式必須呼叫PermissionRequest#grant(String[])或PermissionRequest#deny()。如果沒有覆寫該方法,預設拒絕。
*/
onPermissionRequest(PermissionRequest request)
/**
* 通知主程式相關許可權被取消。任何相關UI都應該隱藏掉。
*/
onPermissionRequestCanceled(PermissionRequest request)
/**
* 通知主程式 執行的Js操作超時。客戶端決定是否中斷JavaScript繼續執行。如果客戶端返回true,JavaScript中斷執行。如果客戶端返回false,則執行繼續。注意:如果繼續執行,重置JavaScript超時計時器。如果Js下一次檢查點仍沒有結束,則再次提示。
*/
onJsTimeout()
/**
*當停止播放,Video顯示為一張圖片。預設圖片可以通過HTML的Video的poster屬性標籤來指定。如果poster屬性不存在,則使用預設的poster。該方法允許ChromeClient提供預設圖片。
*/
getDefaultVideoPoster()
/**
* 當用戶重放視訊,在渲染第一幀前需要花費時間去緩衝足夠的資料。在緩衝期間,ChromeClient可以提供一個顯示的View。如:可以顯示一個載入動畫。
*/
getVideoLoadingProgressView()
/**
* 獲取訪問歷史Item,用於連結顏色。
*/
getVisitedHistory(ValueCallback callback)
/**
* 通知客戶端顯示檔案選擇器。用來處理file型別的HTML標籤,響應使用者點選選擇檔案的按鈕操作。呼叫filePathCallback.onReceiveValue(null)並返回true取消請求操作。
* FileChooserParams引數的列舉列表:
MODE_OPEN 開啟
MODE_OPEN_MULTIPLE 選中多個檔案開啟
MODE_OPEN_FOLDER 開啟資料夾(暫不支援)
MODE_SAVE 儲存
*/
onShowFileChooser(WebView webView, ValueCallback filePathCallback,FileChooserParams fileChooserParams)
/**
* 解析檔案選擇Activity返回的結果。需要和createIntent一起使用。
*/
parseResult(int resultCode, Intent data)
/**
* 建立Intent物件來啟動檔案選擇器。Intent支援可訪問的簡單型別檔案資源。不支援高階檔案資源如live media capture媒體快照。如果需要訪問這些資源或其他高階檔案型別資源可以自己建立Intent物件。
*/
createIntent()
/**
* 返回檔案選擇模式
*/
getMode()
/**
* 返回可訪問MIME型別陣列,如audio/*,如果沒有指定可訪問型別,陣列返回為null
*/
getAcceptTypes()
/**
* 返回優先的媒體快照型別值如Camera、Microphone。true:允許快照。false,禁止快照。使用getAcceptTypes方法確定合適的capture裝置。
*/
isCaptureEnabled()
/**
* 返回檔案選擇器的標題。如果為null,使用預設名稱。
*/
getTitle()
/**
*指定預設選中的檔名或為null
*/
getFilenameHint()
其它事件處理
上面講了有關WebViewClient的用法,但其中還有一些小問題是WebViewClient無法解決的,比如返回按鍵、滾動事件監聽等
1、返回按鍵
如果用webview點連結看了很多頁以後,如果不做任何處理,點選系統“Back”鍵,整個瀏覽器會呼叫finish()而結束自身,如果希望瀏覽的網頁回退而不是退出瀏覽器,需要在當前Activity中處理並消費掉該Back事件。 覆蓋Activity類的onKeyDown(int keyCode, KeyEvent event)方法。
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//改寫物理返回鍵的邏輯
if(keyCode==KeyEvent.KEYCODE_BACK) {
if(mWebView.canGoBack()) {
mWebView.goBack();//返回上一頁面
return true;
} else {
System.exit(0);//退出程式
}
}
return super.onKeyDown(keyCode, event);
}
2、滾動事件監聽
我們都知道監聽滾動事件一般都是設定setOnScrollChangedListener,可惜的是 WebView並沒有給我們提供這樣的方法,但是我們可以重寫WebView,覆蓋裡面的一個方法: protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){} 然後再對外提供一個介面,示例程式碼如下:
public class MyWebView extends WebView {
private OnScrollChangedCallback mOnScrollChangedCallback;
public MyWebView(Context context) {
super(context);
}
public MyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedCallback != null) {
mOnScrollChangedCallback.onScroll(l,t,oldl,oldt);
}
}
public OnScrollChangedCallback getOnScrollChangedCallback() {
return mOnScrollChangedCallback;
}
public void setOnScrollChangedCallback(
final OnScrollChangedCallback onScrollChangedCallback) {
mOnScrollChangedCallback = onScrollChangedCallback;
}
public static interface OnScrollChangedCallback {
public void onScroll(int left,int top ,int oldLeft,int oldTop);
}
}
3、如何強制使用外部瀏覽器開啟網頁
如果不想在 webview 中顯示網頁,而是直接跳轉到瀏覽器的話,可以像下邊那樣呼叫。
Uri uri = Uri.parse("http://www.example.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
這裡是使用隱式Intent的方式來啟用外部應用。