1. 程式人生 > >Android hybrid之JS與Native的通訊方式

Android hybrid之JS與Native的通訊方式

場景

為了降低開發成本和跨平臺一致性的使用者體驗.通常敏捷開發中通常採用混合型應用Hybrid App(Native View與WebView交替呼叫),而Js作為Html頁面中常用的邏輯處理指令碼,掌握JS和Java的相互通訊是非常重要的!

操作步驟

  • webView設定支援JavaScript
  • webView提供JavaScript介面
  • 客戶端和網頁端定義好方法申明.編寫程式碼

Js呼叫Java

ps: 有時候,在webview中有個Button,而點選這個Button.我們的App需要finish掉這個頁面,但是我們在App中是沒法捕捉到這個按鈕的點選事件的,.那麼這時候就需要用到Js 回撥Java的方法來實現了

①佈局檔案

  <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

②Js程式碼

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
</head>
<body>
<title>test html</title
>
<button onclick="window.js.comeplete()">comeplete()</button> <br/> </body> </html>

很簡單,就是一個按鈕,並新增點選事件,這裡需要注意的是我們的呼叫,裡面有一個.js,其實這個是我們在java程式碼中天加的介面名字.

③java程式碼

首先為了能夠支援JavaScript,我們的webView必須setJavaScriptEnabled(true)

mWebView = (WebView) findViewById(R.id.webview);
        // 啟用javascript
mWebView .getSettings().setJavaScriptEnabled(true); // 從assets目錄下面的載入html mWebView .loadUrl("file:///android_asset/js.html"); mWebView .addJavascriptInterface(this, "js");

④最後新增相應的方法

public void comeplete(){
        this.finish();
    }

Java呼叫JS

同樣,有時候,我們又需要根據不同的操作,讓頁面顯示不同的內容,那麼這時候就需要用到Java呼叫JavaScript了/

①這時候,我們的html頁面是這樣的

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<script type="text/javascript">
function javacalljs(){
     document.getElementById("content").innerHTML +=   
         "<br\>java呼叫了js函式";
}

function javacalljswithargs(arg){
     document.getElementById("content").innerHTML +=   
         ("<br\>"+arg);
}

</script>
</head>
<body>
<title>test html</title>
<div id="content">內容顯示</div>
</body>
</html>

②佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

  <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="java呼叫js函式" />
    <Button
        android:id="@+id/button2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="java呼叫js函式(帶引數)" />
</LinearLayout>

③Java程式碼

mWebView = (WebView) findViewById(R.id.webview);
        // 啟用javascript
        mWebView .getSettings().setJavaScriptEnabled(true);
        // 從assets目錄下面的載入html
        mWebView .loadUrl("file:///android_asset/js.html");
        Button button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(btnClickListener);
        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(btnClickListener);

④按鈕的點選事件

OnClickListener btnClickListener = new Button.OnClickListener() {
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.button1:
// 無引數呼叫
    mWebView.loadUrl("javascript:javacalljs()");
                break;
            case R.id.button2:// 傳遞引數呼叫 
                            mWebView .loadUrl("javascript:javacalljswithargs(" + "'hello world,i`m Java'" + ")");
                break;
            default:
                break;
            }       
        }
    };

Android 4.2以後的注入事項

  • @JavascriptInterface

在使用中,我們發現當targetSdkVersion>17的時候就會出現一下異常E/Web Console: Uncaught TypeError: Object [object Object] has no method 'toString'

通過檢視官方文件,解釋如下

From the Android 4.2 documentation:

Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.

意思就是當targetSdkVersion>17的時候,我們需要在暴露給js的介面加上@JavascriptInterface註解

因此4.2 之後的js 呼叫java方式是這樣的

@JavascriptInterface
public void comeplete(){
        this.finish();
    }

呼叫js有引數有返回值的函式

Android在4.4之前並沒有提供直接呼叫js函式並獲取值的方法,所以在此之前,常用的思路是 java呼叫js方法,js方法執行完畢,再次呼叫java程式碼將值返回。

Js程式碼:

function button2click1(){
window.js.showResult(index);
}

Java程式碼

  mWebView.loadUrl("javascript:button2click1()");

// 在回撥中獲取返回值
  @JavascriptInterface
    public void showResult(String s){
        Toast.makeText(this,s+"",Toast.LENGTH_LONG).show();
    }

Android 4.4之後使用evaluateJavascript即可獲取JavaScript返回值.

Js程式碼

var index=0;  
function android_call_js_parameter(arg){  
    index+=Number(arg);
     document.getElementById("content").innerHTML +=("<br\>"+index);  
     return index;
}  

function  button2click(){  
   return 1;
}

Java程式碼

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    mWebView.evaluateJavascript("button2click()",
                    //設定回撥介面
                            new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {
                                    mWebView.loadUrl("javascript:android_call_js_parameter('" + value + "')");
                                }
                            });
                }

效果圖:

Android JavaScript和java 互動