本文主要對WebView進(jìn)行介紹,包括
webView 4個(gè)可以定制的點(diǎn)、
設(shè)置WebView back鍵響應(yīng)、
控制網(wǎng)頁的鏈接仍在webView中跳轉(zhuǎn)、
顯示頁面加載進(jìn)度、
處理https請求、
利用addJavascriptInterface實(shí)現(xiàn)android程序和javascript交互等等
WebView基于webkit引擎展現(xiàn)web頁面的控件,使用前需要在Android Manifest file中配置internet訪問權(quán)限,否則提示頁面無法訪問
Xml代碼 [url=]
[/url]
- <uses-permission
android:name="android.permission.INTERNET"
/>
WebView控件功能強(qiáng)大,除了具有一般View的屬性和設(shè)置外,還可以對url請求、頁面加載、渲染、頁面交互進(jìn)行強(qiáng)大的處理。
WebView有幾個(gè)可以定制的點(diǎn):
(1)設(shè)置
WebChromeClient子類,
WebChromeClient會(huì)在一些影響瀏覽器ui交互動(dòng)作發(fā)生時(shí)被調(diào)用,比如WebView關(guān)閉和隱藏、頁面加載進(jìn)展、js確認(rèn)框和警告框、js加載前、js操作超時(shí)、webView獲得焦點(diǎn)等等,詳見
WebChromeClient(2)設(shè)置
WebViewClient子類,
WebViewClient會(huì)在一些影響內(nèi)容喧嚷的動(dòng)作發(fā)生時(shí)被調(diào)用,比如表單的錯(cuò)誤提交需要重新提交、頁面開始加載及加載完成、資源加載中、接收到http認(rèn)證需要處理、頁面鍵盤響應(yīng)、頁面中的url打開處理等等,詳見
WebViewClient(3)設(shè)置
WebSettings類,
其中包含多項(xiàng)配置。WebSettings用來對WebView的配置進(jìn)行配置和管理,比如是否可以進(jìn)行文件操作、緩存的設(shè)置、頁面是否支持放大和縮小、是否允許使用數(shù)據(jù)庫api、字體及文字編碼設(shè)置、是否允許js腳本運(yùn)行、是否允許圖片自動(dòng)加載、是否允許數(shù)據(jù)及密碼保存等等,詳見
WebSettings(4)設(shè)置
addJavascriptInterface方法,
將java對象綁定到webView中,以方便從頁面js中控制java對象,實(shí)現(xiàn)用本地java代碼和html頁面進(jìn)行交互,甚至可以進(jìn)行頁面自動(dòng)化。但如此做存在安全隱患,所以若設(shè)置了此方法,請確保webView的代碼都是自己完成,詳細(xì)使用addJavascriptInterface進(jìn)行自動(dòng)化見本文5使用addJavascriptInterface完成和js交互
1、back鍵控制網(wǎng)頁后退Activity默認(rèn)的back鍵處理為結(jié)束當(dāng)前Activity,webView查看了很多網(wǎng)頁后,希望按back鍵返回上一次瀏覽的頁面,這個(gè)時(shí)候我們就需要覆蓋onKeyDown函數(shù),告訴他如何處理,如下:
Java代碼 [url=]
[/url]
- public
boolean onKeyDown(int keyCode, KeyEvent event) { - if (webView.canGoBack() && event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
- webView.goBack();
- return
true; - }
- return
super.onKeyDown(keyCode, event); - }
其中webView.canGoBack()在webView含有一個(gè)可后退的瀏覽記錄時(shí)返回true
webView.goBack();表示返回webView的上次訪問頁面
2、當(dāng)前網(wǎng)頁的鏈接仍在webView中跳轉(zhuǎn)Java代碼 [url=]
[/url]
- webView.setWebViewClient(new WebViewClient() {
- @Override
- public
boolean shouldOverrideUrlLoading(WebView view, String url) { - view.loadUrl(url);
- return
true; - }
- });
shouldOverrideUrlLoading表示當(dāng)前webView中的一個(gè)新url需要加載時(shí),給當(dāng)前應(yīng)用程序一個(gè)處理機(jī)會(huì),如果沒有重寫此函數(shù),webView請求ActivityManage選擇合適的方式處理請求,就像彈出uc和互聯(lián)網(wǎng)讓用戶選擇瀏覽器一樣。重寫后return true表示讓當(dāng)前程序處理,return false表示讓當(dāng)前webView處理
Xml代碼 [url=]
[/url]
- Give the host application a chance to take over the control when a new url is about to be loaded in the current WebView. If WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the url. If WebViewClient is provided, return true means the host application handles the url, while return false means the current WebView handles the url.
參考:
http://developer.android.com/reference/android/webkit/WebViewClient.html#shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String)問題分析:
今天在用webView load騰訊的OAuth頁面
http://open.t.qq.com/cgi-bin/authorize時(shí),突然彈出選擇uc還是互聯(lián)網(wǎng)瀏覽器的確認(rèn)框,很奇怪,其他頁面都能正常load,而這個(gè)卻無法在webView中l(wèi)oad,后來用火狐看了下是因?yàn)閘oad這個(gè)頁面的時(shí)候會(huì)重定向到另外一個(gè)頁面
http://open.t.qq.com/oauth_html/login.php?oauth_token=xxx&type=0,而webView沒有設(shè)置shouldOverrideUrlLoading,導(dǎo)致url交給了ActivityManage去處理,解釋如上,后添加后可正常load頁面
3、頁面加載進(jìn)度代碼如下
Java代碼 [url=]
[/url]
- webView.setWebChromeClient(new WebChromeClient() {
- public
void onProgressChanged(WebView view, int progress) { - setTitle("頁面加載中,請稍候..." + progress + "%");
- setProgress(progress * 100);
- if (progress == 100) {
- setTitle(R.string.app_name);
- }
- }
- });
onProgressChanged通知應(yīng)用程序當(dāng)前頁面加載的進(jìn)度
progress
表示當(dāng)前頁面加載的進(jìn)度,為1至100的整數(shù)
參考:
http://developer.android.com/reference/android/webkit/WebChromeClient.html#onProgressChanged(android.webkit.WebView, int)4、處理https請求webView默認(rèn)是不處理https請求的,頁面顯示空白,需要進(jìn)行如下設(shè)置:
Java代碼 [url=]
[/url]
- webView.setWebViewClient(new WebViewClient() {
- @Override
- public
void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - handler.proceed();
- // handler.cancel();
- // handler.handleMessage(null);
- }
- });
onReceivedSslError為webView處理ssl證書設(shè)置
其中handler.proceed();表示等待證書響應(yīng)
handler.cancel();表示掛起連接,為默認(rèn)方式
handler.handleMessage(null);可做其他處理
參考:
http://developer.android.com/reference/android/webkit/WebViewClient.html#onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError)5、使用addJavascriptInterface完成和js交互5.1 javascript中調(diào)用java對象及方法設(shè)置webView的addJavascriptInterface方法,該方法有兩個(gè)參數(shù),第一個(gè)參數(shù)為被綁定到j(luò)s中的類實(shí)例,第二個(gè)參數(shù)為在js中暴露的類別名,在js中引用java對象就是用這個(gè)名字
Java代碼 [url=]
[/url]
- ClassBeBindedToJS classBeBindedToJS = new ClassBeBindedToJS();
- webView.addJavascriptInterface(classBeBindedToJS, "classNameBeExposedInJs");
實(shí)現(xiàn)綁定到j(luò)s的類,其中的javaMethod方法我們將在頁面前端js中調(diào)用,用于返回一段內(nèi)容。showHtml用來使用AlertDialog顯示一段html代碼,稍后將使用到
Java代碼 [url=]
[/url]
- private
class ClassBeBindedToJS{ - public
void showHtml(String html){ - new AlertDialog.Builder(UpdateStatusActivity.this)
- .setTitle("HTML").setMessage(html)
- .setPositiveButton(android.R.string.ok, null)
- .setCancelable(false).create().show();
- }
- public String javaMethod() {
- return
"use java method"; - }
- };
如此我們就可以在前端調(diào)用java對象,如下:
Html代碼 [url=]
[/url]
- <span><html>
- <body>
- <div
id="displayDiv">Test page.</div>
- <input
type="button"
value="use java object"
onclick="document.getElementById('</span>displayDiv').innerHTML=classNameBeExposedInJs.javaMethod()"
/>
- <span>
</body>
- </html></span>
這段html作用為點(diǎn)擊button按鈕,改變div內(nèi)容為java對象方法中的內(nèi)容,其中classNameBeExposedInJs為java對象在js中的別名,javaMethod為java對象的方法
5.2 java中調(diào)用js方法用webView的loadUrl實(shí)現(xiàn),比如現(xiàn)在我們想在頁面加載完成后調(diào)用js中的hello函數(shù),實(shí)現(xiàn)如下:
Java代碼 [url=]
[/url]
- webView.setWebViewClient(new WebViewClient() {
- @Override
- public
void onPageFinished(WebView webView, String url){ - webView.loadUrl("javascript:hello()");
- }
- });
怎么樣,很簡單吧^_^,直接loadUrl("javascript:hello()")就可以了
利用這一點(diǎn)我們可以很方便的實(shí)現(xiàn)WebView的自動(dòng)化,如網(wǎng)頁自動(dòng)化登錄。舉個(gè)栗子,實(shí)現(xiàn)
http://m.renren.com/ 的自動(dòng)登錄啊,代碼如下
Java代碼 [url=]
[/url]
- webView.getSettings().setJavaScriptEnabled(true);
- webView.loadUrl("http://m.renren.com");
- webView.requestFocus();
- ClassBeBindedToJS classBeBindedToJS = new ClassBeBindedToJS();
- webView.addJavascriptInterface(classBeBindedToJS, "classNameBeExposedInJs");
- webView.setWebViewClient(new WebViewClient() {
- @Override
- public
void onPageFinished(WebView webView, String url){ - webView.loadUrl("javascript:document.getElementsByName('email')[0].value='userName'");
- webView.loadUrl("javascript:document.getElementsByName('password')[0].value='userPassword'");
- webView.loadUrl("javascript:document.getElementsByName('login')[0].click()");
- }
- });
從中可以看出先加載http://m.renren.com頁面,在頁面加載完成onPageFinished后,調(diào)用js實(shí)現(xiàn)自動(dòng)登錄
其中三句js分別表示設(shè)置用戶名文本框內(nèi)容、設(shè)置用戶密碼文本框內(nèi)容、點(diǎn)擊登錄按鈕,如此登錄成功嘍
5.3 java和js混用實(shí)現(xiàn)一些效果5.3.1 WebView用AlertDialog顯示頁面的html代碼之前5.1中的showHtml方法現(xiàn)在派上用場啦,在頁面加載完成后顯示頁面html內(nèi)容,如下:
Java代碼 [url=]
[/url]
- webView.setWebViewClient(new WebViewClient() {
- @Override
- public
void onPageFinished(WebView webView, String url){ - webView.loadUrl("javascript:window.classNameBeExposedInJs.showHtml(document.getElementsByTagName('html')[0].innerHTML);");
- }
- });
其中webView.loadUrl表示調(diào)用頁面中的js,而頁面中的js window.classNameBeExposedInJs.showHtml調(diào)用了程序中的java對象的方法,方法參數(shù)為一段js。
首先webView會(huì)執(zhí)行這一段js document.getElementsByTagName('html')[0].innerHTML。含義即為取得頁面中html標(biāo)記的innerHTML,及網(wǎng)頁主要內(nèi)容;
然后將得到的網(wǎng)頁內(nèi)容當(dāng)作字符串參數(shù)傳入showHtml方法
最后調(diào)用showHtml函數(shù)實(shí)現(xiàn),即用AlertDialog顯示字符串,如此得到了整個(gè)網(wǎng)頁的大部分html代碼
5.3.2 WebView顯示當(dāng)前頁面的url地址獲得WebView當(dāng)前頁面url使用webView.getUrl()即可,如下:
Java代碼 [url=]
[/url]
- webView.loadUrl("javascript:window.classNameBeExposedInJs.showHtml('" + webView.getUrl() + "');");