Cordova/Phonegap Android中Java調用JavaScript

前言

最近被一個小需求搞得焦頭爛額的,連睡覺都會夢見自己在寫代碼.在兩位大大的幫助下,今天終於解決了.趕緊把它記錄下來先.

需求

這個需求是這樣子的:在BroadcastReceiver中接收推送的消息,然後將收到的消息發給Javascript處理.看起來一點都不復雜是不是?但是網上一搜,結果都是JavaScript調用Java的,Java調用JavaScript的資料很少.
最終找到了兩種方法,但原理都是一樣的,只有一點區別而已.即要先在JS中通過插件調用Java,然後再調回JS.那麼問題來了,我並不知道什麼時候會接收到推送的消息,我又怎麼知道在哪發起JS的請求?

解決方法

最終的解決方法還是要用到那兩種方法,不過有一點變通.先說一下這兩種方法吧.等不及的可以直接看最後,看看解決思路是怎樣的.
無論哪種方法,都要先自定義插件.關於如何自定義插件,我就不詳細說明了,網上有很多相關的資料.

自定義插件

plugin.xml:

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    xmlns:rim="http://www.blackberry.com/ns/widgets"
    xmlns:android="http://schemas.android.com/apk/res/android"
    id="cordova-plugin-androidCallJS"
    version="1.0.0">

    <description>Android native call javascript</description>
    <name>AndroidCallJS</name>
    <author>hope</author>

    <js-module src="www/AndroidCallJS.js" name="AndroidCallJS">
        <clobbers target="AndroidCallJS" />
    </js-module>

    <platform name="android">
        <config-file target="res/xml/config.xml" parent="/*">
            <feature name="AndroidCallJS">
                <param name="android-package" value="com.example.test" />
            </feature>
        </config-file>

        <source-file src="src/android/AndroidCallJS.java" target-dir="src/com/example/test/plugin/" />
    </platform>
</plugin>

AndroidCallJS.js

var exec = cordova.require('cordova/exec');

var AndroidCallJS = function() {};

AndroidCallJS.prototype.javacalljs = function(successCallback, errorCallback, options) {
    exec(successCallback, errorCallback, "AndroidCallJS", "callJS", [options]);
};

module.exports = {
    init: function() {
        return new AndroidCallJS();
    },
    AndroidCallJS: AndroidCallJS
};  

AndroidCallJS.java

package com.example.test;

import android.app.Activity;
import android.webkit.JavascriptInterface;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;

public class AndroidCallJS extends CordovaPlugin {

    private Activity activity;
    private CordovaWebView webView;

    public AndroidCallJS() {
    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        this.activity = cordova.getActivity();
        this.webView = webView;
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("callJS")) {
            callback();
            return true;
        }
        return false;
    }

    @JavascriptInterface
    public void callback() {
        callJS("update('success')");
    }

    private void callJS(final String js) {
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                webView.loadUrl("javascript:" + js);
            }
        });
    }
}

第一種方法

參考資料:cordova升級到5.0後,如何實現java調用 js更新 ui

function javacalljs() {
    var callJS = AndroidCallJS.init();
    callJS.javacalljs(function success() {
        alert('success callback.');
    }, function error() {
        alert('error callback.');
    }, "");
}

第二種方法

參考資料:cordova混合開發

cordova.require('cordova/channel').onCordovaReady.subscribe(function() {
    cordova.require('cordova/exec')(onSuccess, null, 'AndroidCallJS', 'callJS', []);
    function onSuccess(msg) {
        // JS回調函數
    }
});

這裏只是簡單的寫了一下,具體的可以參見上面給出的參考資料,裏面說得很詳細.

解決問題思路

最後是找到了這裏才知道應該怎麼解決的.原理就是在應用啓動的時候由JS發起請求調用安卓的插件,然後在插件中動態註冊BroadcastReceiver,在onReceive中收到消息後通過callback.success(msg)將消息返回給JS處理.

End

說白了原理其實很簡單,可是對Cordova不熟的話就很難想出這樣的解決方案了.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章