DaoCloud+是一个使用 Electron 迷你的托盘控制台程序,而且在写这个程序的时候最重要的原因就是希望能及时获取到我的镜像构建和应用运行(接口原因,目前无法支持)状态,但如果应用不能主动推送通知给我,那么这个应用能提供给我的价值就是微乎其微了。
那么现在问题来了,在没有官方的推送服务支持时,如果能够实现应用主动推送呢?让官方去支持这个几乎是不可能,所以惯性思维让我第一想到这个解决方案定时请求API,对比上次状态作出通知。然后这种做法实在是在Low而且低效了,而且如果构建时间短于你的轮询时间,就会无法捕获到状态的变化了。
不过有个好消息是,目前很多平台都支持了Webhook,开发者通过自定义回调函数的方式来获取一些事件的消息,DaoCloud是支持镜像构建和持续集成的事件通知的,所以通过这个我们起码能实时获取到状态的变化而不需要去轮询API接口了,只需要将消息转发给客户端就可以了。
最后一个问题是通过什么方式来接收服务端的消息了,我没有去看过任何关于Mac平台上如何关于推送的资料(之前一个为了实现iOS应用的推送,各种什么证书啊什么的折腾死了,Android就好太多了),毕竟我们用的是Electron,所以只需要使用提供JavaScript SDK的推送服务即可,之前做客户一般都是使用了 极光推送、小米推送、百度推送* 等等,但这些一律都只是支持Android和iOS,而且目前只发现国内只有云巴(不是广告,不是软文,后面有强力吐槽)提供了JavaScript,毕竟这此公司的定位不一样。
云巴的JS-SDK是基于socket.io实现的,当然也是可以支持Electron或者NW.js这种框架啦,而且在使用上和Web的没有任何的不同。
现在开始
首先基于 electron-boilerplate 脚手架搭建项目的基本目录结构,以下是daocloud-plus已经按需整理好的目录结构
.
├── CHANGELOGS.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── app
│ ├── app.html
│ ├── app.js
│ ├── background.js
│ ├── components
│ ├── env.js
│ ├── helpers
│ ├── images
│ ├── node_modules
│ ├── package.json
│ ├── stylesheets
│ └── vendor
├── build
├── config
├── gulpfile.js
├── node_modules
├── package.json
├── releases
├── resources
└── tasks
客户端
客户端这边需要生成一个别名(为了保证不重复这里使用了UUID)并且订阅即可。
DaoCloud那边只需要添加些Webhook即可
示例:http://daocloud-plus.blankapp.org/b131a88748f84b3f956839d3e9879baf
编写相关消息接收代码
/app/app.html
...
<!-- 引入云巴 JS SDK -->
<script src="./vendor/yunba/yunba-js-sdk.js"></script>
<script src="./vendor/yunba/socket.io-1.3.5.js"></script>
...
/app/app.js
...
// 从 localStorage 获取别名,如果不存在则创建
var yunba_alias = localStorage.getItem('yunba_alias');
if (!yunba_alias) {
yunba_alias = uuid.v4();
yunba_alias = replaceall("-", "", yunba_alias);
localStorage.setItem('yunba_alias', yunba_alias);
}
// 初始化云巴SDK
yunba.init(function (success) {
if (success) {
// 连接服务器
yunba.connect(function (success, msg) {
if (success) {
// 设置别名,成功后服务端的消息将会在set_message_cb方法接收
yunba.set_alias({'alias': yunba_alias}, function (data) {
if (data.success) {
console.log('别名:' + yunba_alias + " 设置成功");
} else {
console.log(data.msg);
}
});
} else {
console.error(msg);
}
});
} else {
console.error(msg);
}
});
// 云巴消息监听
yunba.set_message_cb(function (data) {
console.log(data);
// 创建一个通知
var notification = new Notification('DaoCloud Plus', {
body: data.msg
});
});
...
服务端
服务端要做的事情就更加简单了,接收Webhook的发送过来的数据,通过云巴的REST接口发送给客户端即可,这里为了快速使用了 Laravel 框架,为什么这么简单的一个事情还要使用一个框架,那是因为我对PHP不熟,不想折腾~~
使用 laravel 创建 daocloud-plus-notifier 项目
$ larave new daocloud-plus-notifier
编写相关消息推送代码
/app/Http/routes.php
...
// 配置路由
// 示例:http://daocloud-plus.blankapp.org/b131a88748f84b3f956839d3e9879baf
Route::post('/{alias}', 'NotifierController@webhook');
...
/app/Http/Controllers/NotifierController.php
<?php
namespace App\Http\Controllers;
use GuzzleHttp\Client;
use Validator;
use Lang;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class NotifierController extends Controller
{
protected function webhook(Request $request, $alias)
{
$name = $request->input('name');
$build = $request->input('build');
if (!$build) {
return $this->failure();
}
// 根据 build_type 和 status 组装消息
$msg = Lang::get('daocloud.' . $build['build_type'] . '_' . strtolower($build['status']), ['name' => $name]);
// 向别名发送消息,通过 env 方法获取到云巴的 AppKey 和 SecretKey
$client = new Client();
$response = $client->request('GET', 'http://rest.yunba.io:8080', [
'query' => [
'method' => 'publish_to_alias',
'appkey' => env('YUNBA_APPKEY', ''),
'seckey' => env('YUNBA_SECRET_KEY', ''),
'alias' => $alias,
'msg' => $msg
]
]);
if ($response->getStatusCode() == 200) {
return $this->success();
}
return $this->failure();
}
}
编码完成
到此编码工作已经完成,代码比较简单,但是已经实现了给 Electron 程序添加了消息通知功能了。
头脑风暴
通过Electron+Webhook+云巴就可以快速实现了一个实用的Mac应用,其实通过Webhook可能做的事情还有很多很多,例如做一个基于Webhook的通知中心(哈哈,我竟然嫌现在的通知还不够多啊~)等等
相关文章
项目地址
吐槽一下云巴
不提供包依赖管理工具的支持
我不太清楚目前的公司开发有没有使用依赖管理工具,但是我个人认为直接以文件的方式引入SDK的方式实在是太Low并且低效了
例如Android,我只需要在build.gradle文件添加
compile 'com.squareup.retrofit2:retrofit:2.0.2'
例如iOS,只需要在Podfile添加一行
pod 'AFNetworking', '~> 3.0'
例如NPM,只需要执行一行命令
$ npm install lowdb --save
例如PHP,同样只需要一行命令
$ composer require fzaninotto/faker
等等...
然而,国内能提供包依赖管理工具支持的实在是少得可怜~~~
过于业余的接口命名规范
表示无法理解使用 publish2
这种命名~~
功能点相关概念重叠
在云巴的SDK里,alias
是基于 topic
来实现的,但是文档并没有说明,如果 alias
完全是基于 topic
的,那 alias
存在的意义是什么?
创建新应用时必须填写Android包名
以目前个人的理解,云巴不同于目前市面那些移动应用推送平台,并不局限于移动应用,但是在后台创建应用的时候为什么必须让我填写Android的包名?
运行提供官方提供的Demo过于麻烦
Android 的 Demo 可不可以直接用AndroidStudio来写啊?
有时候运行一个Demo的时候都要花上几个小时~~~
[建议] 为开发者创造使用场景
云巴这个平台个人感觉还是很优秀的(仅限提供的实时数据交换服务),可以做的事情太多了,但是官方给我们展现出的一些使用场景太少了,而且在这个推送市场如此饱和的市场,很难让我下定决心去选择使用在自己的项目上。这个时候官方应该为开发者创造更多的使用场景~~
以上吐槽同样适用于国内其他提供开发者服务的平台
为什么要吐槽
我们使用第三方提供的服务是为了什么?就是为了能够快速实现我需要的功能,然而大部分的服务提供商提供给开发者的包括SDK、文档往往是和快速实现背道而驰的,往往在很多项目中,我们使用到的仅仅是一个很小的功能,但却要进行非常复杂的配置等等。
关于我
如果你对这个项目或者这篇文章感兴趣,欢迎 Follow 我