Android WebView使用 – Android移動開發技術文章_手機開發 Android移動開發教學課程

 

本文主要對WebView進行介紹,包括webView 4個可以定制的點、設置WebView back鍵響應、控制網頁的鏈接仍在webView中跳轉、顯示頁面加載進度、處理https請求、利用addJavascriptInterface實現android程序和javascript交互等等

 

 

 

WebView基於webkit引擎展現web頁面的控件,使用前需要在Android Manifest file中配置internet訪問權限,否則提示頁面無法訪問

 

Xml代碼 

<uses-permission android:name="android.permission.INTERNET" /> 

 

<uses-permission android:name="android.permission.INTERNET" />WebView控件功能強大,除瞭具有一般View的屬性和設置外,還可以對url請求、頁面加載、渲染、頁面交互進行強大的處理。

 

WebView有幾個可以定制的點:

 

(1)設置WebChromeClient子類,WebChromeClient會在一些影響瀏覽器ui交互動作發生時被調用,比如WebView關閉和隱藏、頁面加載進展、js確認框和警告框、js加載前、js操作超時、webView獲得焦點等等,詳見WebChromeClient

 

 

 

(2)設置WebViewClient子類,WebViewClient會在一些影響內容喧嚷的動作發生時被調用,比如表單的錯誤提交需要重新提交、頁面開始加載及加載完成、資源加載中、接收到http認證需要處理、頁面鍵盤響應、頁面中的url打開處理等等,詳見WebViewClient

 

 

 

(3)設置WebSettings類,其中包含多項配置。WebSettings用來對WebView的配置進行配置和管理,比如是否可以進行文件操作、緩存的設置、頁面是否支持放大和縮小、是否允許使用數據庫api、字體及文字編碼設置、是否允許js腳本運行、是否允許圖片自動加載、是否允許數據及密碼保存等等,詳見WebSettings

 

 

 

(4)設置addJavascriptInterface方法,將java對象綁定到webView中,以方便從頁面js中控制java對象,實現用本地java代碼和html頁面進行交互,甚至可以進行頁面自動化。但如此做存在安全隱患,所以若設置瞭此方法,請確保webView的代碼都是自己完成,詳細使用addJavascriptInterface進行自動化見本文5使用addJavascriptInterface完成和js交互

 

 

 

1、back鍵控制網頁後退

 

Activity默認的back鍵處理為結束當前Activity,webView查看瞭很多網頁後,希望按back鍵返回上一次瀏覽的頁面,這個時候我們就需要覆蓋onKeyDown函數,告訴他如何處理,如下:

 

Java代碼 

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);  

 

    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含有一個可後退的瀏覽記錄時返回true

 

webView.goBack();表示返回webView的上次訪問頁面

 

 

 

2、當前網頁的鏈接仍在webView中跳轉

 

Java代碼 

webView.setWebViewClient(new WebViewClient() {  

 

    @Override 

    public boolean shouldOverrideUrlLoading(WebView view, String url) {  

        view.loadUrl(url);  

        return true;  

    }  

}); 

 

                webView.setWebViewClient(new WebViewClient() {

 

                    @Override

                    public boolean shouldOverrideUrlLoading(WebView view, String url) {

                        view.loadUrl(url);

                        return true;

                    }

                }); shouldOverrideUrlLoading表示當前webView中的一個新url需要加載時,給當前應用程序一個處理機會,如果沒有重寫此函數,webView請求ActivityManage選擇合適的方式處理請求,就像彈出uc和互聯網讓用戶選擇瀏覽器一樣。重寫後return true表示讓當前程序處理,return false表示讓當前webView處理

 

Xml代碼 

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. 

 

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.參考:

 

https://developer.android.com/reference/android/webkit/WebViewClient.html#shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String)

 

 

 

問題分析:

 

今天在用webView load騰訊的OAuth頁面https://open.t.qq.com/cgi-bin/authorize

 

時,突然彈出選擇uc還是互聯網瀏覽器的確認框,很奇怪,其他頁面都能正常load,而這個卻無法在webView中load,後來用火狐看瞭下是因為load這個頁面的時候會重定向到另外一個頁面https://open.t.qq.com/oauth_html/login.php?oauth_token=xxx&type=0,而webView沒有設置shouldOverrideUrlLoading,導致url交給瞭ActivityManage去處理,解釋如上,後添加後可正常load頁面

 

 

 

3、頁面加載進度

 

代碼如下

 

Java代碼 

webView.setWebChromeClient(new WebChromeClient() {  

 

    public void onProgressChanged(WebView view, int progress) {  

        setTitle("頁面加載中,請稍候…" + progress + "%");  

        setProgress(progress * 100);  

 

        if (progress == 100) {  

            setTitle(R.string.app_name);  

        }  

    }  

}); 

 

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通知應用程序當前頁面加載的進度

 

progress  表示當前頁面加載的進度,為1至100的整數

 

參考:

 

https://developer.android.com/reference/android/webkit/WebChromeClient.html#onProgressChanged(android.webkit.WebView, int)

 

 

 

4、處理https請求

 

webView默認是不處理https請求的,頁面顯示空白,需要進行如下設置:

 

Java代碼 

    webView.setWebViewClient(new WebViewClient() {  

 

        @Override 

        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  

            handler.proceed();  

//            handler.cancel();  

//            handler.handleMessage(null);  

        }  

    }); 

 

    webView.setWebViewClient(new WebViewClient() {

 

        @Override

        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {

            handler.proceed();

//            handler.cancel();

//            handler.handleMessage(null);

        }

    });onReceivedSslError為webView處理ssl證書設置

 

其中handler.proceed();表示等待證書響應

 

handler.cancel();表示掛起連接,為默認方式

 

handler.handleMessage(null);可做其他處理

 

參考:

 

https://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中調用java對象及方法

 

設置webView的addJavascriptInterface方法,該方法有兩個參數,第一個參數為被綁定到js中的類實例,第二個參數為在js中暴露的類別名,在js中引用java對象就是用這個名字

 

Java代碼 

ClassBeBindedToJS classBeBindedToJS = new ClassBeBindedToJS();  

webView.addJavascriptInterface(classBeBindedToJS, "classNameBeExposedInJs");  

 

ClassBeBindedToJS classBeBindedToJS = new ClassBeBindedToJS();

webView.addJavascriptInterface(classBeBindedToJS, "classNameBeExposedInJs"); 

 

實現綁定到js的類,其中的javaMethod方法我們將在頁面前端js中調用,用於返回一段內容。showHtml用來使用AlertDialog顯示一段html代碼,稍後將使用到

 

Java代碼 

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";  

    }  

}; 

 

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";

    }

};如此我們就可以在前端調用java對象,如下:

 

Html代碼 

<SPAN><html> 

    <body>          

        <p id="displayDiv">Test page.</p> 

        <input type="button" value="use java object" onclick="document.getElementById('</SPAN>displayDiv').innerHTML=classNameBeExposedInJs.javaMethod()" /> 

<SPAN>  </body> 

</html></SPAN> 

 

<html>

       <body>       

              <p id="displayDiv">Test page.</p>

              <input type="button" value="use java object" onclick="document.getElementById('displayDiv').innerHTML=classNameBeExposedInJs.javaMethod()" />

       </body>

</html> 這段html作用為點擊button按鈕,改變p內容為java對象方法中的內容,其中classNameBeExposedInJs為java對象在js中的別名,javaMethod為java對象的方法

 

 

 

5.2 java中調用js方法

 

用webView的loadUrl實現,比如現在我們想在頁面加載完成後調用js中的hello函數,實現如下:

 

Java代碼 

webView.setWebViewClient(new WebViewClient() {    

    @Override 

    public void onPageFinished(WebView webView, String url){  

        webView.loadUrl("javascript:hello()");  

    }  

}); 

 

webView.setWebViewClient(new WebViewClient() { 

    @Override

    public void onPageFinished(WebView webView, String url){

        webView.loadUrl("javascript:hello()");

    }

});怎麼樣,很簡單吧^_^,直接loadUrl("javascript:hello()")就可以瞭

 

利用這一點我們可以很方便的實現WebView的自動化,如網頁自動化登錄。舉個栗子,實現https://m.renren.com/ 的自動登錄啊,代碼如下

 

Java代碼 

webView.getSettings().setJavaScriptEnabled(true);  

webView.loadUrl("https://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()");  

    }  

}); 

 

webView.getSettings().setJavaScriptEnabled(true);

webView.loadUrl("https://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()");

       }

});從中可以看出先加載https://m.renren.com頁面,在頁面加載完成onPageFinished後,調用js實現自動登錄

 

其中三句js分別表示設置用戶名文本框內容、設置用戶密碼文本框內容、點擊登錄按鈕,如此登錄成功嘍

 

 

 

5.3 java和js混用實現一些效果

 

5.3.1WebView用AlertDialog顯示頁面的html代碼

 

之前5.1中的showHtml方法現在派上用場啦,在頁面加載完成後顯示頁面html內容,如下:

 

Java代碼 

webView.setWebViewClient(new WebViewClient() {    

    @Override 

    public void onPageFinished(WebView webView, String url){  

        webView.loadUrl("javascript:window.classNameBeExposedInJs.showHtml(document.getElementsByTagName('html')[0].innerHTML);");  

    }  

}); 

 

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表示調用頁面中的js,而頁面中的js window.classNameBeExposedInJs.showHtml調用瞭程序中的java對象的方法,方法參數為一段js。

 

首先webView會執行這一段js document.getElementsByTagName('html')[0].innerHTML。含義即為取得頁面中html標記的innerHTML,及網頁主要內容;

 

然後將得到的網頁內容當作字符串參數傳入showHtml方法

 

最後調用showHtml函數實現,即用AlertDialog顯示字符串,如此得到瞭整個網頁的大部分html代碼

 

 

 

5.3.2WebView顯示當前頁面的url地址

 

獲得WebView當前頁面url使用webView.getUrl()即可,如下:

 

Java代碼 

webView.loadUrl("javascript:window.classNameBeExposedInJs.showHtml('" + webView.getUrl() + "');"); 

 

webView.loadUrl("javascript:window.classNameBeExposedInJs.showHtml('" + webView.getUrl() + "');");參考:

 

https://developer.android.com/reference/android/webkit/WebView.html

/kf/201110/108835.html

發佈留言