1. 程式人生 > >安卓混合開發例項——JS與Java的互動

安卓混合開發例項——JS與Java的互動

今天說說安卓混合開發。
曾經有一個話題是web終會一統app,然後我們看到隨著時間的推移。web越來越強大(H5啊,JS各種框架啊),但同時原生app也在不斷髮展。
或許在將來還會再有這種話題論戰,但目前,混合開發,結合web和原生app二者各自的優勢,已經是眾望所歸了。

其中最常見的一種方式,在安卓的webview中巢狀web,通過各類設計,讓二者進行互動。使得使用者體驗上幾乎無法分辨出究竟是否純原生。
這種方式最值得深入研究的就是,安卓中的java程式碼與web端的javascript程式碼進行相互互動呼叫。

簡單介紹一下背景知識:(Java和JavaScript)

說到java,作為目前(以及此前這麼多年來)最受青睞最有用武之地的語言,就不多介紹了。貼百科:
Java具有簡單性、面向物件、分散式、健壯性、安全性、平臺獨立與可移植性、多執行緒、動態性等特點[2] 。Java可以編寫桌面應用程式、Web應用程式、分散式系統和嵌入式系統應用程式等[3] 。

說到javascript。貼百科:JavaScript一種直譯式指令碼語言,是一種動態型別、弱型別、基於原型的語言,內建支援型別。它的直譯器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用於客戶端的指令碼語言,最早是在HTML(標準通用標記語言下的一個應用)網頁上使用,用來給HTML網頁增加動態功能。

這麼晦澀難懂? 那就簡單一句話,其實java和JavaScript,完全是兩碼事。前者是面向物件,後者是內建物件。且後者借鑑了前者,但二者並沒有關係.

好了,來到正題吧,先上效果圖。

這裡寫圖片描述

圖中,
上半部分(藍色背景)是安卓中實現的簡單佈局
下半部分(白色背景)是一個webview,裡面的內容自然就是一個網頁。

但是我們看到,點選上半部分安卓中的檢視,能夠改變webview中網頁的檢視。
同樣,點選下半部分網頁中的Button,能夠呼叫安卓的Toast對話方塊。

這就是簡單的一個android與web互動,目前在安卓界普遍稱為JS互動

理論的東西講完了,接下來上程式碼:
今天的主角其實是兩方面:安卓和web,
但我們分為4個類:
1.index.html,這是一個簡單的web頁面。
2.activity_main.xml 安卓的佈局
3.MainActivity 安卓的主介面,同時也是本例的入口
4.JsInterface,這個類其實算幫助類,只是為了程式碼好看才抽出來

1.首先是index.html: web的佈局及函式 (注意,這個檔案要放在安卓的assets檔案下

)

<html>
<!-- 簡單寫,就省略了head -->
<body>
    <script language="javascript">
        //這個方法是與java事先商定的方法,讓java來呼叫
        function java_call_Js(param) {
            var x = document.getElementById('test');
            x.innerHTML = "Hello , New text form java ! ------------>" + param;
        }

        //Html自身Button的方法,去呼叫Java
        function btn_js() {
            jsInterface.js_call_java();
        }
    </script>

    <input type="button" onClick="btn_js()"
        style="height: 60px; width: 240px; margin-top: 40px ; margin-bottom: 10px"
        value="(JS call Java)I'm a Button in html">

    <div id="test">
        <font color="#FF0000">this is the old text</font>
    </div>
</body>

2.其次是activity_main: 安卓的佈局

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#336699"
        android:gravity="center_vertical"
        android:orientation="vertical" >

        <EditText
            android:id="@+id/text_edit"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="請輸入你想在html顯示的數字(不輸入引數會報空指標)"
            android:inputType="number"
            android:maxLength="7"
            android:textColor="#ffffff" />

        <Button
            android:id="@+id/btn_java"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="java call js(I&apos;m a Button in Android" />
    </LinearLayout>

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

3.其三是MainActivity: 主要的邏輯程式碼

public class MainActivity extends Activity {

    private EditText mEditText;
    private Button mButton;
    private WebView webview;
    private JsInterface jsInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mEditText = (EditText) findViewById(R.id.text_edit);
        mButton = (Button) findViewById(R.id.btn_java);
        webview = (WebView) findViewById(R.id.webview);

        // 例項化介面JsInterface
        jsInterface = new JsInterface(webview);
        // 初始化WebSetting
        initWebSetting();

        webview.loadUrl("file:///android_asset/index.html");
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void initWebSetting() {

        // 允許JS互動
        webview.getSettings().setJavaScriptEnabled(true);
        // 設定JS的介面
        webview.addJavascriptInterface(jsInterface, "jsInterface");

        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                mButton.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        int param = Integer.parseInt(mEditText.getText().toString());
                        jsInterface.java_call_Js(param);
                        param = 0;
                    }
                });
            }
        });
    }
}

4.最後是JsInterface,封裝了兩個函式

//雖然命名為Interface,其實是偽介面,主要是為了方便理解及以後做抽象處理
public class JsInterface {
    private WebView mWebView;

    // 構造方法,傳入一個引數WebView
    public JsInterface(WebView webView) {
        this.mWebView = webView;
    }

    // 這個方法是js呼叫java
    @JavascriptInterface
    public void js_call_java() {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                // 主執行緒更新UI
                Toast.makeText(mWebView.getContext(), "I'm a function in java", Toast.LENGTH_SHORT).show();
            }
        });
    }

    // 這個方法 是java呼叫js
    public void java_call_Js(int param) {
        // 這裡呼叫html中的js程式碼的 java_call_Js 方法
        mWebView.loadUrl(String.format("javascript:java_call_Js(" + param + ")"));
    }
}

註釋都有,就不多說了。

在模擬器上執行程式碼,就會看到如上的效果圖
這裡主要看互動的雙方(安卓和html):
都保留著兩個方法(一個用來被對方呼叫,一個去呼叫對方)。
所有,做JS的前提是,要達成一種約定。要明確了對方的什麼物件的什麼方法可以被呼叫,才能如魚得水。

另外這個地方值得注意:

        // 允許JS互動 ------>意味著可能會被JS注入等攻擊,安全問題需要考慮//
        webview.getSettings().setJavaScriptEnabled(true);

        // 設定JS的介面--------->第二個引數"jsInterface" 定義了給html中使用的物件就叫jsInterface
        webview.addJavascriptInterface(jsInterface, "jsInterface")

        //html中使用這個物件的程式碼就是:   jsInterface.js_call_java();