Android WebView詳解(二):Android原生與JS互調

Android 去調用JS 的代碼

  • 經過WebView的loadUrl()javascript

    先寫一個html,很簡單的一個代碼,alert顯示。html

    android_load_js.htmljava

    <!DOCTYPE html>
      <html>
         <head>
            <meta charset="utf-8">
            <title>Android調用 JS 代碼demo</title>
      // JS代碼
           <script>
             // Android須要調用的方法
             function callJS(){
                alert("Android調用了JS的callJS方法");
             }
          </script>
         </head>
      </html>

    在Activity中android

    mWebSettings = mWebview.getSettings();
      //與JS交互開關
      mWebSettings.setJavaScriptEnabled(true);
      //設置容許JS彈窗	    
      mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
      mWebview.loadUrl("file:///android_asset/android_load_js.html");
    
      //在這我用了一個TextView 點擊事件中去調用JS中的方法
      beginLoading.setOnClickListener(new View.OnClickListener() {
          [@Override](https://my.oschina.net/u/1162528)
          public void onClick(View view) {
              //執行JS方法
        		mWebview.loadUrl("javascript:callJS()");
          }
      });
    
    
      mWebview.setWebChromeClient(new WebChromeClient() {
          //獲取網站標題
          [@Override](https://my.oschina.net/u/1162528)
          public void onReceivedTitle(WebView view, String title) {
              System.out.println("標題在這裏");
              mtitle.setText(title);
          }
    
          //獲取加載進度
          [@Override](https://my.oschina.net/u/1162528)
          public void onProgressChanged(WebView view, int newProgress) {
              if (newProgress < 100) {
                  String progress = newProgress + "%";
                  loading.setText(progress);
              } else if (newProgress == 100) {
                  String progress = newProgress + "%";
                  loading.setText(progress);
              }
          }
    
      	//因爲設置了彈窗檢驗調用結果,因此須要支持js對話框
          //webview只是載體,內容的渲染須要使用webviewChromClient類去實現
          //經過設置WebChromeClient對象處理JavaScript的對話框
          //設置響應js 的Alert()函數
          [@Override](https://my.oschina.net/u/1162528)
          public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
              AlertDialog.Builder b = new AlertDialog.Builder(TestActivity.this);
              b.setTitle("Alert");
              b.setMessage(message);
              b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                  [@Override](https://my.oschina.net/u/1162528)
                  public void onClick(DialogInterface dialog, int which) {
                      result.confirm();
                  }
              });
              b.setCancelable(false);
              b.create().show();
              return true;
          }
      });
  • 經過WebView的evaluateJavascript()web

    該方法比第一種方法效率更高,由於該方法的執行不會使頁面刷新,而第一種方法(loadUrl)的執行則會。該方法在Android 4.4 後纔可以使用,該方法在主線程執行ide

    //將上面webView.loadUrl("javascript:callJS()")替換爲
      mWebview.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
          @Override
          public void onReceiveValue(String value) {
              //此處爲 js 返回的結果
          }
      });

    能夠作一下兼容:函數

    if (Build.VERSION.SDK_INT > 18) {
          mWebview.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
              @Override
              public void onReceiveValue(String value) {
                  //此處爲 js 返回的結果
              }
          });
      } else {
          mWebview.loadUrl("javascript:callJS()");
      }

JS 去調用 Android的代碼

  • 經過WebView的addJavaScriptInterface()進行對象映射測試

    html網站

    <!DOCTYPE html>
      <html>
         <head>
            <meta charset="utf-8">
            <title>DEMO</title>
            <script>
               function callAndroid(){
              // 因爲對象映射,因此調用test對象等於調用Android映射的對象
                  test.showLog("js調用了android中的hello方法");
               }
            </script>
         </head>
         <body>
            //點擊按鈕則調用callAndroid函數
            <button type="button" id="button1" onclick="callAndroid()" text="Android"></button>
         </body>
      </html>

    映射的代碼ui

    package org.professor.procartoon.temp;
    
      import android.webkit.JavascriptInterface;
    
      import org.professor.procartoon.utils.LogUtils;
    
      /**
       * Created by Caipeng on 2018.02.06.
       */
      public class JSObject {
    
      	/**
      	 * 定義JS須要調用的方法被JS調用的方法必須加入@JavascriptInterface註解
      	*/
          @JavascriptInterface
          public void showLog(String text) {
              LogUtils.i(text);
          }
      }

    在Activity中的測試代碼

    mWebSettings.setJavaScriptEnabled(true);
      mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
      //經過addJavascriptInterface()將Java對象映射到JS對象
      //參數1:Javascript對象名
      //參數2:Java對象名
      mWebview.addJavascriptInterface(new JSObject(),"test");
      mWebview.loadUrl("file:///android_asset/android_load_js.html");
  • 經過WebViewClient的ShouldOverrideUrlLoading() 方法進行回調攔截

    Android經過 WebViewClient 的回調方法shouldOverrideUrlLoading ()攔截 url,解析該 url 的協議,若是檢測到是預先約定好的協議,就調用Android相應的方法。

    html Document

    <!DOCTYPE html>
      <html>
         <head>
            <meta charset="utf-8">
            <title>DEMO</title>
            <script>
               function callAndroid(){
      			//協議org://professor?arg1=com&arg2=test
                  document.location = "org://professor?arg1=111&arg2=222";
               }
            </script>
         </head>
         <body>
            //點擊按鈕則調用callAndroid函數
             <button type="button" id="button1" onclick="callAndroid()">CallAndroid</button>
         </body>
      </html>

    JAVA代碼

    @Override
      public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
          //通常根據scheme(協議格式) & authority(協議名)判斷(前兩個參數)
          Uri uri = Uri.parse(request.getUrl().toString());
          if (uri.getScheme().equals("org")) {
              if (uri.getAuthority().equals("professor")) {
                  LogUtils.i(uri.getQueryParameter("arg1"));
              }
              return true;
          }
    
          return super.shouldOverrideUrlLoading(view, request);
      }

    備註

    JS獲取Android方法的返回值複雜。 若是JS想要獲得Android方法的返回值,只能經過 WebView 的loadUrl ()去執行 JS 方法把返回值傳遞回去,相關的代碼以下:

    //Android原生調用js
      mWebView.loadUrl("javascript:returnResult(" + result + ")");
    
      //須要在html中接收
      function returnResult(result){
          alert("result is" + result);
      }
  • 經過WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調攔截JS對話框alert()、confirm()、prompt() 消息

    首先介紹下JS中的alert()、confirm()、prompt()三個方法

    • alert(),彈出警告窗,沒有返回值,在文本加入\n可換行
    • confirm(),彈出確認框,兩個返回值,返回布爾值,經過該值能夠判斷點擊是確認仍是取消(true表示點擊了確認,false表示點擊了取消)
    • prompt(),彈出輸入框,任意設置返回值,點擊確認返回輸入框中的值,點擊取消返回null

    原理:Android經過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調分別攔截JS對話框 (即上面的三個方法),獲得他們的消息內容,而後解析便可。

    經常使用的攔截是:攔截 JS的輸入框(即prompt()方法)。由於只有prompt()能夠返回任意類型的值,操做最全面方便、更加靈活;而alert()對話框沒有返回值confirm()對話框只能返回兩種狀態(肯定 / 取消)兩個值

    html代碼

    <!DOCTYPE html>
      <html>
         <head>
            <meta charset="utf-8">
            <title>DEMO</title>
            <script>
               function callAndroid(){
                  //document.location = "org://professor?arg1=111&arg2=222";
                  var result=prompt("org://professor?arg1=111&arg2=222");
                  alert("demo " + result);
               }
            </script>
         </head>
         <body>
            //點擊按鈕則調用callAndroid函數
             <button type="button" id="button1" onclick="callAndroid()">CallAndroid</button>
         </body>
      </html>

    JAVA代碼

    @Override
      public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    
          //通常根據scheme(協議格式) & authority(協議名)判斷(前兩個參數)
          Uri uri = Uri.parse(url);
          if (uri.getScheme().equals("org")) {
              if (uri.getAuthority().equals("professor")) {
                  LogUtils.i(uri.getQueryParameter("arg1"));
                  //參數result:表明消息框的返回值(輸入值)
                  result.confirm("js調用了Android的方法成功啦");
              }
              return true;
          }
    
          return super.onJsPrompt(view, url, message, defaultValue, result);
      }
  • 結語

    由上能夠比較,根據第三種方式,即:經過WebChromeClient的方法攔截比較靈活一些

相關文章
相關標籤/搜索