最近的一个多月里,都在忙于为项目上的移动应用,添加一个聊天的功能。不是从头开始写聊天,而是基于第三方的 SDK。这个 SDK 里提供了基本的聊天接口,因此我们所要做的就是编写一个 Cordova 插件来实现聊天。
由于第三方 SDK 已经提供了大部分的功能,我们只需要封装好相应的 Cordova 插件,再调用相应的接口即可。
开始介绍之前,我们要先了解一下 Cordova 插件通讯。
我假设读者已经有一点相关的 Cordova 插件的使用经验:
如果你不知道上述的内容,可以参考这篇文章《Cordova插件 / 混合应用插件开发: hello,world解析》 进行详细的了解。
对于一个 Cordova 插件来说,返回数据可以有两种形式(sendJavascript已经不推荐使用):
大部分情况下,我们都使用回调来返回结果:
callbackContext.sendPluginResult(new PluginResult(Status.OK, result));
如果需要一直返回值的话,我们还需要保持这个回调的状态:
pluginResult.setKeepCallback(true);
如,当我们想监听系统的电池状态时,我们可以注册一个 receiver:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
this.receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateBatteryInfo(intent);
}
};
webView.getContext().registerReceiver(this.receiver, intentFilter);
一旦状态发生变化(Intent.ACTION_BATTERY_CHANGED)的时候,我们就触发这个事件:updateBatteryInfo(intent);
。
随后,不断地向 WebView 发送对应的状态变化即可。在相应的映射 javascript 代码里,触发这个事件:cordova.fireWindowEvent("batterystatus", info);
。
而后,在我们的前端,我们只需要监听相应的事件即可:
window.addEventListener("batterystatus", onBatteryStatus, false);
function onBatteryStatus(status) {
console.log("Level: " + status.level + " isPlugged: " + status.isPlugged);
}
除了这个方法,还可以采用的作法是:在前端直接执行 JavaScript 代码。
当我们只有一个地方调用方法来返回值的时候,保持长回调是一件很简单的事。而当我们有 2~3 处的地方需要同时监听这个状态改变的时候,它就不能适用于这种场景。
这个时候,我们就可以直接通过 UiThread 来执行 JavaScript 代码。而在这个代码里,我们实际上是触发一个 JavaScript 事件:
var event = document.createEvent('Events');
event.initEvent('messages.arrived', true, true);
event.messages={};
document.dispatchEvent(event);
对应的,我们只需要在 Java 代码里将 JavaScript 代码交给 WebView 去 load 就可以了:
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
String js = "";
webView.loadUrl("javascript:" + js);
}
});
而后,我们就可以直接在监听事件,并执行相应的业务功能了。
为了在 Angular 里监听相应的事件,我做了一些麻烦的事——先由 Ionic 去监听事件,再通过 Angular 的广播来发送事件。这样做可以帮助我建立一层隔离。
在初始化代码里,可以使用 $window 来监听事件:
$window.addEventListener('LaunchUrl', function(event) {
})
也可以使用 Ionic 来监听事件:
$ionicPlatform.on('LaunchUrl', function(event) {
});
然后再通过 Angular 的广播来通知所有的组件:
$rootScope.$broadcast("LaunchUrl", LaunchUrl);
围观我的Github Idea墙, 也许,你会遇到心仪的项目