前言
最近被一個小需求搞得焦頭爛額的,連睡覺都會夢見自己在寫代碼.在兩位大大的幫助下,今天終於解決了.趕緊把它記錄下來先.
需求
這個需求是這樣子的:在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不熟的話就很難想出這樣的解決方案了.