1. 程式人生 > >Android開發之Webview中原生與JS互動

Android開發之Webview中原生與JS互動

文章目錄

概述

由於手機硬體資源的快速提升,使得采用混合開發的可能性逐漸成為現實並且流行起來。Android開發中最為簡單的方式就是通過Webview來嵌入一個網頁使web作為App的一部分。

使用場景

  1. 非重互動場景
  2. 非計算密集型場景
  3. 對UI複雜度要求不高的場景
    以上可見,《王者榮耀》斷然不會使用混合開發的,其實谷歌舉了兩個最適合的場景:
    第一:內容需要動態更新的場景,例如APP裡面的法律條款展示等。
    第二:總是需要通過網路來拉取展示內容的場景,例如新聞展示。

互動方式

我們知道,網頁的行為現在是使用JavaScript來處理的,而Android原生使用的是Java(Kotlin),互動的意思即原生可以呼叫JavaScript方法,而JavaScript也可以呼叫原生的方法。

Java呼叫JS程式碼的方法有2種:

  1. 通過WebView的loadUrl() 方法
  2. 通過WebView的evaluateJavascript()方法

JS呼叫Java程式碼的方法有3種:

  1. 通過WebView的addJavascriptInterface()進行物件對映
  2. 通過 WebViewClient 的shouldOverrideUrlLoading ()方法回撥攔截 url
  3. 通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回撥攔截JS對話方塊alert()、confirm()、prompt() 訊息

先上一張效果圖:
在這裡插入圖片描述

Java呼叫JS程式碼

上面提到Android提供了兩種方法來實現Java執行Js程式碼,其中evaluateJavascript()方法是從 API 19(4.4版本)開始提供的,而現在Android已經發布到 API 28 (9.0)了, 4.4以下版本佔的比例已經非常少了,相信過不了多久基本上就不存在了,所以我們要放下歷史包袱,直接使用新的方法。最重要的是,在Android 4.4及其以上版本Google 採用了 Chromium

(http://www.chromium.org/) 作為系統WebView的底層核心,而不是WebKit了。新的webview對HTML5,CSS3,Javascript的支援更為廣泛,而且js執行引擎直接換成了V8,執行效率大大提升.

void evaluateJavascript(String script, ValueCallback<String> resultCallback){}

引數script : 要執行的JS程式碼。
引數 resultCallback: Js程式碼執行後的返回值

具體步驟:
第一:新建一個工程,新建一個Activity,包含一個Webview控制元件。
第二:新建一個demo.html的文件,作為要在webview中展示的web頁面,裡面含有js程式碼。將其放在工程中的assets檔案家中。

<!DOCTYPE html>
<html>
<head lang="zh-cmn-Hans">
    <meta charset="UTF-8">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport" content="width=device-width"/>
    <title>JsBridgeDemo</title>
</head>
<style>
    .btn {
        text-align: center;
        background: #d8d8d8;
        color: #222;
        padding: 20px;
        margin: 30px;
        font-size: 24px;
        border-radius: 4px;
        box-shadow: 4px 2px 10px #999;
    }

    .btn:active {
        opacity: .7;
        box-shadow: 4px 2px 10px #555;
    }
</style>

<body>
<div class="btn" onclick="showAndroidToast('Js呼叫Java')">Js呼叫Java函式</div>
<p id="content"></p>

<script type="text/javascript">
    function showAndroidToast(toast) {
        android.showToast(toast);
    }

   function fillContent(){
      document.getElementById("content").innerHTML ="此處內容由Java呼叫Js方法展示在Webview上";
      return "ok";
   }
</script>
</body>

第三步:在activity中通過webview呼叫Js程式碼。

  final WebView myWebView=findViewById(R.id.webView);
  WebSettings webSettings=myWebView.getSettings();
  webSettings.setJavaScriptEnabled(true);
  myWebView.loadUrl("file:///android_asset/demo.html");
  Button btnCallJs=findViewById(R.id.btn_call_js);
  btnCallJs.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          myWebView.evaluateJavascript("fillContent()", new ValueCallback<String>() {
              @Override
              public void onReceiveValue(String value) {
                  Toast.makeText(MainActivity.this,value,Toast.LENGTH_SHORT).show();
              }
          });
      }
  });        

首先設定允許Webview執行Js,然後載入assets資料夾中的demo.html網頁,最後在點選按鈕的時候使用evaluateJavascript()方法來執行Js程式碼。

JS程式碼的呼叫需要在web頁面載入完成後才可以正常執行。可以通過監聽WebViewClient的onPageFinished 回撥來完成,如下程式碼所示。

 myWebView.setWebViewClient(new WebViewClient(){
          @Override
          public void onPageFinished(WebView view, String url){
              super.onPageFinished(view, url);
              //執行Js程式碼
          }
      });

JS呼叫Java程式碼

上面提到有三種方法可以實現Js呼叫Java程式碼的目的,其中第一種簡單明瞭,為Google推薦的方法,但是其在API 17(4.2)之前存在任意執行漏洞。但是我們前面分析了,4.4 都快沒有了,4.2 就更別說了,所以我們直接針對Android4.4程式設計,使用這個方法是安全的。

具體步驟:
第一步:新建一個介面類JavaInterface ,裡面定義給Js呼叫的方法。這些方法必須是public的,而且必須使用@JavascriptInterface進行註解,例如下面的程式碼示例中的showTost()

public class JavaInterface {
    private Context mContext;

    JavaInterface(Context c) {
        mContext = c;
    }

    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}

第二步:給Webview新增與Js的對映關係

myWebView.addJavascriptInterface(new JavaInterface(this),"android");

引數1:介面類的物件
引數2:Java物件對映到Js的物件名,可以在Js中使用這個物件來呼叫介面類中的方法。

第三步:在Js中呼叫Java方法

<script type="text/javascript">
    function showAndroidToast(toast) {
        android.showToast(toast);
    }
</script>

可以看到,在js中可以使用android這個Js物件,直接呼叫我們定義在JavaInterface類中的方法。

總結

以上就是Android開發中使用Webview 完成原生與web的互動。開篇說道除了本文介紹的方式,還有其他幾種方式,大部分不是有歷史包袱就是本意不是用來做這件事情的,所以應該優先使用本文的方式,如果有的同學需要了解其他方法,可以參考這篇部落格,寫的比較全。

如果是在專案中使用而不是為了學習,推薦使用前人寫好的三方庫,例如DSBridge,JsBridge等。特別是dsbridge,三端全有,現代簡潔,易用。