前言
最近被一个小需求搞得焦头烂额的,连睡觉都会梦见自己在写代码.在两位大大的帮助下,今天终于解决了.赶紧把它记录下来先.
需求
这个需求是这样子的:在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不熟的话就很难想出这样的解决方案了.