Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 通過webView與javascript交互來研究webView的特點

通過webView與javascript交互來研究webView的特點

編輯:關於Android編程

1、前言

webView是android中用於展示簡單的網頁或者加載一些html格式的很好的選擇,它提供了很多的操作上的封裝但同時又不失去靈活性,因為他提供了webViewClient和webChromeClient這兩個可自定義的類來進行對頁面動作的不同產生不同的表現的行為。在hybrid app開發模式中,webView可用於和web網頁交互的能力也是一個很突出的亮點,很多時候都會需要用到這樣的技術。所以接下來會通過講解webView,webViewCient,webChromeClient之間互相的關系和作用,然後綜合所講內容來展示一個webView與web的javascript進行交互的場景。首先了解可定義webView頁面表現行為的類。讀者可先看webView的部分在回來看前面的部分,會比較好理解。

2、WebViewClient

此類可以作用與當webView的頁面內容發生改變的時候或者需要提交表單數據的時候又或者發生錯誤的時候,進行對url或者內容的攔截處理,來進一步定義我們的操作內容。在WebViewClient中,有以下幾個要點是比較重要的。

2.1 在新的請求前攔截URL

默認情況下,如果webView沒有設置webViewClient的話,有新的請求加載的時候是由當前的activityManager進行處理請求的,但如果我們想在webView加載url的時候先攔截下來,自己處理的話,就需要給webView設置攔截器,即設置一個webViewClient並重寫shouldOveeriedUrlLoading方法。該方法原型如下:

 

 public boolean shouldOverrideUrlLoading(WebView view, String url)

此方法可以讓程序對url(post方式的請求除外)請求進行控制,當此方法返回true的時候表示程序會對url進行處理,返回false的時候表示webView會自己對url進行處理。而如果webView沒有進行此方法重寫的話,則當前的url會有系統負責處理。

 

2.2 判斷當前頁面是否開始加載或者加載完畢

webViewClient可以通過onPageStarted和onPageFinished來判斷當前webView中某個頁面是否開始加載或者是否加載完畢。方法原型如下:

 

 public void onPageStarted(WebView view, String url, Bitmap favicon) 
public void onPageFinished(WebView view, String url)
啟動view表示調用了此方法的webView,url是當前正在加載的鏈接。favicon是與當前頁面有關的一個標志,用於判斷當前的頁面是否加載過。

 

 

2.3 獲取請求資源的數據

webViewCLient允許你攔截資源請求並獲取返回的內容,方法原型如下:

 

 public WebResourceResponse shouldInterceptRequest
如果此方法返回的是Null,則webView會像往常一樣去加載url的內容,否則的話就會用獲取的數據來初始化內容。需要注意的是此方法不在主線程運行。

 


2.4獲取請求失敗的原因

webView中定義了很多常量用於描述url加載失敗的原因,通過重寫onReceiverError方法就可以獲取失敗的代碼和失敗信息。方法原型如下:

 

public void onReceivedError(WebView view, int errorCode,
            String description, String failingUrl)

其中errorCode加載失敗的代碼,description是失敗的描述,failingUrl是失敗的鏈接。每個errorCode都有對應的消息。下面貼出它們的意義:

 

\

\


 

 

2.5 webView的縮放模式發生改變

如果webView的縮放模式發生改變的時候,所請求的資源也需要發送變化,那麼就需要監聽webView的縮放比例了。可以通過webVewClient的onScaleChanged方法來進行攔截。

 public void onScaleChanged(WebView view, float oldScale, float newScale)
其中oldScale表示原來的縮放比例,newScale表示新的縮放比例。這裡要注意的是,對於高分辨率的手機,縮放比例默認是1.5X,普通的是1x,低分辨率的是0.75x。

3、 WebChromeClient

這個類可用於設計跟webView的ui相關的操作,比如請求進度的更新,或者js的彈窗或者標題的展現以及圖標.....此類中最近常用的到的方法如下:

3.1獲取請求進度

webChromeClient可以獲取當前請求的url的進度情況,很經常用於展示在標題欄裡面展示當前的進度信息。方法原型如下:

 

 public void onProgressChanged(WebView view, int newProgress) 

其中的newProgress就是當前的請求進度情況,通過設置activityd的setProgress方法就可以進行展示請求進度,當達到100%的時候,進度會自動消失。

 

3.2獲取請求的網站標題和圖標

webChromeClient提供了兩個方法,可用於獲取當前請求的Url的網站標題和圖標,這樣如果又需要的話,可以自己在標題欄設置相應的標題內容和圖標信息,方法原型如下:

 

 public void onReceivedTitle(WebView view, String title) 

public void onReceivedIcon(WebView view, Bitmap icon)

 

 

 

3.3進行js彈窗提示

webChromeClient可以在客戶端彈出js對話框的時候進行回調,以確認是由客戶端對對話框進行處理還是交給webView進行處理。方法原型如下:

 

  public boolean onJsAlert(WebView view, String url, String message,
            JsResult result)

 public boolean onJsConfirm(WebView view, String url, String message,
            JsResult result)

 public boolean onJsPrompt(WebView view, String url, String message,
            String defaultValue, JsPromptResult result)
 public boolean onJsBeforeUnload(WebView view, String url, String message,
            JsResult result)


message是用於展示的提示消息,jSresult是客戶端返回給javascript的結果。第一個方法彈出js的警告對話框,第二個是確認對話框,第三個是提示對話框,第四個是導航對話框。

 



3.4獲取請求資源的權限

當前頁面需要請求客戶端資源的時候,會需要一些權限,因此webChromeClient提供了請求權限的處理方法,方法原型如下:

 

 public void onPermissionRequest(PermissionRequest request)

此方法只有兩種處理方式,一種是PermissionRequest.grant方法用於同意,另外是deny方法用於拒絕。如果沒有重寫這個方法,默認是拒絕的。

 

3.5webView加載視頻時指定顯示圖標

當webView含有視屏播放的時候,如果還沒顯示視頻,會展示一個圖標的。如果沒有指定,將返回默認的圖標,可以通過以下方法返回指定圖標。

 

 public Bitmap getDefaultVideoPoster()

 

 

4、WebView

WebView是Android提供的一個用於展示網頁內容的控件,如果你想實現一個簡單的浏覽器或者展示一些在線內容的話,就需要用到它。在webView中,展現網頁內容用到的是webkit渲染引擎,並且實現了很多基本的功能,比如會記錄你的浏覽歷史,這樣你可以進行回退或者前進查找網頁。還有查找文字、縮放網頁比例等。既然我們用到webView去加載網頁內容,所以就需要網絡權限,記得,要加上網絡權限。

默認情況下,webView是沒有實現任何浏覽器插件功能的,如果你僅僅是展現網頁內容,那麼webView是個很好的選擇,但如果網頁內容需要和用戶交互的話,你必須讓webView響應javaScript的動作。如果你沒有實現webView的這些交互功能,建議使用Uri意圖調用系統的浏覽器處理網頁內容請求比較合適。調用方法如下:

Uri uri=Uri.parse("htttp://baidu.com");

startActivity(new Intent(Intent.ACTION_VIEW,Uri));

要使用webView,可以在XML布局添加WbeView標簽,並在onCreate方法中獲取進行基本的交互設置。也可以自己new一個,然後調用setContentView方法將整個acitivty都被webView覆蓋,如下:
 

WebView webView=new WebView();

setContentView(webView);

使用webView加載網頁可以使用loadUrl方法,如下:
 

webView.loadUrl("Http://baidu.com“);

或者你可以加載html格式的資源,可以是靜態資源文件也可以是字符串內容。比如:

String html="

content;

webView.loadData(html,"text/html",null);

前面的部分講到了webViewClient和webChromeClient,這兩個方法可以定義很多webView基於不同的事件的不同相應,因此,一般情況下,如果不是僅僅展示html內容的話,都需要重寫這兩個對象來定義相應的實現。通常webChromeClient用於在webView的ui發生變化的時候的被調用,比如根據請求的網頁獲取當前的進度,在標題欄進行展示。webViewClient則用於處理webView中內容發生變化的時候,比如發送了錯誤或者進行了表單提交等。一般來說,如果想要webView進行URL請求處理,都需要重寫shouldOverriedUrlLoading方法,這樣,就可以攔截Url請求讓webView自己處理,否則的話,會讓應用拋出給系統調用,即喚起系統浏覽器進行處理。

如果想要和頁面進行交互,那麼就必須允許webView與javaScript交互,由於webView默認是禁止的,所以需要我們自己設置。一般首先使用過調用webView.getSettings.setJavaScriptEnable方法進行設置。如果你還需要和網頁進行數據交互,還需自行寫一個java對象注入當前的頁面中,這樣javascript可以調用這個注入的對象來和應用交互。

下面給出一個官方的例子:

getWindow().requestFeature(Window.FEATURE_PROGRESS);
 *
 * webview.getSettings().setJavaScriptEnabled(true);
 *
 * final Activity activity = this;
 * webview.setWebChromeClient(new WebChromeClient() {
 *   public void onProgressChanged(WebView view, int progress) {
 *     // Activities and WebViews measure progress with different scales.
 *     // The progress meter will automatically disappear when we reach 100%
 *     activity.setProgress(progress * 1000);
 *   }
 * });
 * webview.setWebViewClient(new WebViewClient() {
 *   public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
 *     Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
 *   }
 * });
 *
 * webview.loadUrl("http://developer.android.com/")

至於如何和網頁進行交互,是本文的重點,會在後面通過一個例子來講解。

前面講到過webView是可以進行方法縮小的,但是默認是不允許此動作的,所以要進行設置,如下:

webView.getSettings.setBuiltInZoomEnable(true);

這樣設置之後,就會出現方法縮小的按鈕,或者你可以用手勢對頁面進行放大縮小。

因為webView是用來浏覽網頁數據的,因此會涉及很多安全性問題,所以對於網頁的cookie和緩存,每個應用都有自己的緩存文件,並且這些文件是不可以共享的。

由於機器的配置發生改變會導致activit進行重新加載資源,而這些也會導致webView重新加載頁面,所以如果你不想發送,webView重新加載頁面的現象,就需要在AndroidMenifest.xml中配置condigurationChange的相關屬性。

由於android設備的屏幕差別很大,根據不同的分辨率有不同的像素密度,所以進行屏幕適配是必須的。對於webView來說,也是如此。android簡單的把所有的設備分為三個等級,分別為高分辨率,普通分辨率和低分辨率手機,webView默認的展示內容的尺寸是普通分辨率。如果是高分辨率,webView將會放大1.5倍,如果是低分辨率則會縮小到0.75倍。這樣就保證了在不同的手機上可以展示相同的內容。同時,根據分辨率的不同還可以設置目標css樣式來達到不同的效果。

如何判斷當前設備的分辨率呢,可以通過在js中調用window.devicePixelRatio這個屬性來判斷,如果返回的是1.5表示是高分辨率,1表示是普通的,0.75表示是低分辨率。

如果要支持html5播放視頻,請記得打開硬件加速器,打開方法是在AndroidMenifest.xml標簽中設置。當加載視屏或者網頁的時候希望全屏現實的話,則需要重寫webChromeClient中的onShowCustomView和onHideCustomView方法,記住這兩個方法缺一不可,否則無法實現全屏。如果在適配加載過程中,需要顯示自定義視圖,可以重寫getVideoLoadingProgressView方法。

最後請記住,使用webView的時候不要用wrap_content屬性,必須使用確切的數值或者match_[arent來指定寬高,否則的話會到值wbView發生奇奇怪怪的顯示現象。在webView中提供的很多方法都是委托webViewProvider實現的,在這裡不講webViewProvider是因為,它的方法基本和webView中的意思連同名字都是一樣的,所以沒有講的必要,但是我們要知道這一點,即webView本身只是一個展示網頁內容的控件,雖然他可以定制,但是卻需要很多支持。下面將webView中比較重要的方法:

①、獲取標題欄高度

public int getVisibleTitleHeight()

此方法用於獲取可見的標題欄高度,注意是可見。

②、獲取SSL安全證書

  public SslCertificate getCertificate()

如果訪問的連接含有SSL安全證書,則返回,否則返回NULL。

③、為指定的主機存儲Http憑證

  public void setHttpAuthUsernamePassword(String host, String realm,
            String username, String password)

用於給指定的主機或者域名存儲Http身份憑證,這樣在訪問的時候就可以今夕身份驗證。

④、加載網絡請求

 public void loadUrl(String url)


注意如果使用此方法加載了頁面之後,點擊頁面的內容需要跳轉到其他頁面的話,系統默認是調用浏覽器處理,如果你希望webView去加載,就應該重寫webViewClient的shouldOvrriedLoadUrl方法。

⑤、用post方式訪問網絡請求

 public void postUrl(String url, byte[] postData)


此方法會用於進行post方式訪問連接,如果當前的url不是網絡請求的話,就會調用loadUrl去加載數據,否則的話會攜帶postData數據去請求連接。

⑥、加載本地數據

public void loadData(String data, String mimeType, String encoding) 

這裡需要解釋的是encoding,它用於指示data的加密方式,如果是base64加密的話,encoding必須是”Base64",否則的話,就傳值NULL,這樣系統會自己去處理data數據的解碼。

⑦、返回上一個網頁

public void goBack() 

如果沒有上一個網頁,則會一直停留在當前頁面。可通過canGoBack方法判斷是否可以返回上一個頁面。

⑧、滾到到頁面頂部或者底部

 public boolean pageUp(boolean top) 
 public boolean pageDown(boolean bottom)
傳值true,當前webView的內容就會滾動帶頁面頂部或者底部。

⑨、獲取Url

 public String getOriginalUrl() 
 public String getUrl()
前者用於獲取原始的鏈接地址,後者用於獲取當前頁面的訪問地址。

⑩、進行js交互

 public void addJavascriptInterface(Object object, String name)


其中object是你定義的類,裡面可以包含提供給js調用app的方法,name是js調用java對象的名稱,這個名稱在js和APP中必須保持一致。下面給出一個官方的例子:
class JsObject {
     *    {@literal @}JavascriptInterface
     *    public String toString() { return "injectedObject"; }
     * }
     * webView.addJavascriptInterface(new JsObject(), "injectedObject");
     * webView.loadData("
", "text/html", null); * webView.loadUrl("javascript:alert(injectedObject.toString())");

這裡不解釋了 ,後面我會用一個例子來講解。要移除一個javaScript對象,可以調用:
public void removeJavascriptInterface(String name)
同時為了可以相應js操作,需要調用:
 public WebSettings getSettings()
以及:

下面的方法是在WebSetting裡面的

  public abstract void setJavaScriptEnabled(boolean flag)
下面講解一個通過webView來與網頁的javascript交互的例子綜合使用上述所講內容:

首先需要在APP中定義一個類,此類應該定義一些可被js調用的方法。如下
 

 class JavaScriptInterface {
        @JavascriptInterface
        public void setParams(String busType, String entName, String startTimeOne, String startTimeTwo, String taskStatus) {
            activity.busType = busType;
            activity.entName = entName;
            activity.startTimeOne = startTimeOne;
            activity.startTimeTwo = startTimeTwo;
            activity.taskStatus = taskStatus;
        }
    }
類的名字是自己取得,沒有限制,可被調用的方法必須加上@javascriptInterface注解,這樣才能將這個方法注解到webView對象中。此類筆者是作為activity的內部類來使用的,所以setParams並不是什麼強制的方法,這個完全是看你自己定義,我這裡只是提供一個接口給js,這樣js就可以把相應的查詢操作產生的參數設置到APP端 了。

接下來看xml布局文件:




    

請讀者忽略webView之外的內容。這裡只講解怎麼進行交互,讀者需要自行篩選出有用的信息。

然後看activity代碼:

   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_PROGRESS);
        setContentView(R.layout.activity_main);
        handler = new Handler();
        webView = (WebView) findViewById(R.id.webView);
        webView.setWebChromeClient(new WebChromeClient() {
                                       @Override
                                       public void onProgressChanged(WebView view, int newProgress) {
                                           MainActivity.this.setProgress(newProgress * 1000);
                                       }
                                   }
        );
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setUseWideViewPort(true); //設置自適應
        webView.getSettings().setLoadWithOverviewMode(true);
        webView.getSettings().setBuiltInZoomControls(true);//設置可縮放
        webView.getSettings().setPluginState(WebSettings.PluginState.ON);//設置插件狀態從而播放視頻
        webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        webView.getSettings().setSavePassword(true);
        webView.getSettings().setSaveFormData(true);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.requestFocus();
        webView.addJavascriptInterface(new JavaScriptInterface(), "webViewInterface");//注意這句話,和後面的js代碼關聯
        webView.loadUrl("http://192.168.191.1:8080/sdfer/");//這是筆者的調試地址,讀者自行修改
        
    }




下面看一下js代碼,重點關注如何執行webView給js注入的對象


<script type="text/javascript">

        function putParams()
        {
             if(window.webViewInterface!=null)
             {
                 var busType=$("#bustype").val();
                 busType=busType==null?"":busType;
                 var entName=$("#entname").val();
                 entName=entName==null?"":entName;
                 var startTimeOne=$("#startTimeOne").val();
                 startTimeOne=startTimeOne==null?"":startTimeOne;
                 var startTimeTwo=$("#startTimeTwo").val();
                 startTimeTwo=startTimeTwo==null?"":startTimeTwo;
                 var taskStatus=$("#taskstatus").val();
                 taskStatus=taskStatus==null?"":taskStatus;
                 window.webViewInterface.setParams(busType,entName,startTimeOne,startTimeTwo,taskStatus);//重點在這裡
             }

        }

</script>


我們看看

 window.webViewInterface.setParams(busType,entName,startTimeOne,startTimeTwo,taskStatus);

webViewInterface就是我們調用addJavascriptInterface給的名稱,這個方法是我們自定義的提供給js調用的方法。以上就實現了js端調用客戶端的方法的過程。

那麼如何在客戶端調用js方法呢?

比如,我們在javascript中定義一個方法,如下:

  function invokeFromAPP(msg){
    alert("來自客戶端的信息:"+msg);
  }


在客戶端的代碼中,對webView執行操作,如下:

webView.loadUrl("javascript:invokeFromAPP('" + msg + "')");

這樣就實現了客戶端調用js方法的操作了。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved