Blog

Blog

PHODAL

Ionic 与 Cordova 插件编写:基于事件与广播的机制

最近的一个多月里,都在忙于为项目上的移动应用,添加一个聊天的功能。不是从头开始写聊天,而是基于第三方的 SDK。这个 SDK 里提供了基本的聊天接口,因此我们所要做的就是编写一个 Cordova 插件来实现聊天。

由于第三方 SDK 已经提供了大部分的功能,我们只需要封装好相应的 Cordova 插件,再调用相应的接口即可。

开始介绍之前,我们要先了解一下 Cordova 插件通讯。

Cordova 插件通讯

我假设读者已经有一点相关的 Cordova 插件的使用经验:

  • 了解怎样添加 Cordova 插件
  • 了解 Cordova 插件中的 plugin.xml 与 www 目录下相应的平台的关系
  • 了解 www 目录的 js 与对应的原生平台代码的关系

如果你不知道上述的内容,可以参考这篇文章《Cordova插件 / 混合应用插件开发: hello,world解析》 进行详细的了解。

对于一个 Cordova 插件来说,返回数据可以有两种形式(sendJavascript已经不推荐使用):

  • 使用 callbackContext 回调返回结果
  • 在 UI 线程上创建事件来返回结果

使用 callbackContext 回调返回结果

大部分情况下,我们都使用回调来返回结果:

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 代码。

在 UI 线程上创建事件来返回结果

当我们只有一个地方调用方法来返回值的时候,保持长回调是一件很简单的事。而当我们有 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);
    }
});

而后,我们就可以直接在监听事件,并执行相应的业务功能了。

Ionic 广播

为了在 Angular 里监听相应的事件,我做了一些麻烦的事——先由 Ionic 去监听事件,再通过 Angular 的广播来发送事件。这样做可以帮助我建立一层隔离。

在初始化代码里,可以使用 $window 来监听事件:

$window.addEventListener('LaunchUrl', function(event) {
})

也可以使用 Ionic 来监听事件:

$ionicPlatform.on('LaunchUrl', function(event) {

});

然后再通过 Angular 的广播来通知所有的组件:

$rootScope.$broadcast("LaunchUrl", LaunchUrl);

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签