最近在研究使用SignalR实现跨平台的消息中心,WebAPI+SignalR作为数据接口和消息中心,客户端包含WPF桌面应用、Web应用和Android移动应用。这其中关键的功能点在于接收到实时消息后的通知提醒,桌面应用和Web应用实现相对简单,Android移动应用开发由于没有相关经验所以花费了一些时间。
环境 | 版本 |
---|---|
操作系统 | Windows 10 proffesional |
编译器 | HBuilder8.8.0 |
编译器 | Eclipse |
测试环境 | Android4.2/7.0 |
服务端的开发有了前面的经验已经驾轻就熟了,包含三个简单方法:上线提醒、下线提醒、消息发送,代码如下:
public class MessageHub : Hub
{
public override Task OnConnected()
{
Clients.Others.listen("[" + DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + "]:" + Context.ConnectionId + ",上线了!");
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
Clients.Others.listen("[" + DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + "]:" + Context.ConnectionId + ",下线了!");
return base.OnDisconnected(stopCalled);
}
public async Task Welcome(string name)
{
string message = "[" + Context.ConnectionId + "][" + System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + "]:" + name;
await Clients.All.listen(message);
}
}
详细的代码可以参考以前的博文
WebAPI集成SignalR
Android客户端采用HTML5开发,一方面是考虑和Web端的通用性,另一方面是因为本人不会原生Android开发。Android客户端处理过程如下:与服务端建立连接,监听消息,接收消息,创建通知。
SignalR的JavaScript客户端代码在网上很多,具体原理和配置不再啰嗦。由于编译器使用的是HBuilder(基于Eclipse开发),就使用了它自带的MUI框架,省去了界面设计的麻烦。
创建一个MUI框架的移动应用项目:
需要注意的是,MUI和JQuery的通配符存在冲突,这个问题必需解决。常用的方法是将 符号给JQuery使用,MUI的$全部使用mui代替。
引用SignalR的js类库:
<script src="js/mui.min.js">script>
<script type="text/javascript" src="js/jquery-1.6.4.min.js" >script>
<script type="text/javascript" src="js/jquery.signalR-2.2.2.min.js" >script>
<script type="text/javascript" src="js/common.js" >script>
<link href="css/mui.min.css" rel="stylesheet"/>
HTML界面:
<body>
<div>
<input type="button" id="_start" value="打开连接" />
<input type="button" id="_stop" value="断开连接" />
<input type="button" id="_clear" value="清空记录" />
div>
<div>
<ul id="_messageList">ul>
div>
<form class="mui-input-group">
<div class="mui-input-row">
<input type="text" id='_msg' placeholder="请输入">
div>
<div class="mui-button-row">
<input type="button" id='_send' value="发送"/>
div>
form>
body>
js代码:
<script type="text/javascript" charset="utf-8">
mui.init();
mui.plusReady(function () {
var startBtn = $('#_start');
var stopBtn = $('#_stop');
var listener = $.hubConnection('http://192.168.1.100/MessageBus',{ useDefaultPath: false });
var hub=listener.createHubProxy('MessageHub');
enable(stopBtn, false);
enable(startBtn, true);
//启动
startBtn.click(function () {
startConnection();
enable(stopBtn, true);
enable(startBtn, false);
});
//停止
stopBtn.click(function () {
stopConnection();
enable(startBtn, true);
enable(stopBtn, false);
});
//清空列表
$('#_clear').click(function () {
$('#_messageList').children().remove();
});
//开启连接
function startConnection() {
hub.on('listen',function (message) {
$('#_messageList').append('' + message + '');
});
listener.start().fail(function () {
$('#_messageList').append('打开连接失败! ');
}).done(function () {
$('#_messageList').append('连接已打开... ');
});
}
//断开连接
function stopConnection() {
listener.stop();
$('#_messageList').append('连接已断开... ');
};
//按钮切换
function enable(button,enabled) {
if (enabled) {
button.removeAttr("disabled");
}
else {
button.attr("disabled", "disabled");
}
}
//发送消息
$('#_send').click(function(){
var msg=$('#_msg').val();
hub.invoke('Welcome',msg);
$('#_msg').val('');
});
});
script>
Native.js实际上是HTML5标准的一部分,并不是一门语言,能够将手机操作系统的原生对象转义,映射为JS对象,简单讲就是使用js操控手机操作系统。有了Native.js,对于像我这样的.NET程序员开发手机应用是再好不过了。
根据查找的资料编写了一段用来创建通知栏消息的代码:
function CreateNotification(m,n){
var NotifyID = n;
var Context = plus.android.importClass("android.content.Context");
var main = plus.android.runtimeMainActivity();
var Noti = plus.android.importClass("android.app.Notification");
var NotificationManager = plus.android.importClass("android.app.NotificationManager");
var nm = main.getSystemService(Context.NOTIFICATION_SERVICE)
var Notification = plus.android.importClass("android.app.Notification");
var mNotification = new Notification.Builder(main);
var pending=plus.android.importClass("android.app.PendingIntent");
var intent=plus.android.importClass("android.content.Intent");
//mNotification.setOngoing(true);
mNotification.setContentTitle("您有一条未读消息");//标题
mNotification.setContentText(m);//内容
mNotification.setSmallIcon(17301620);//图标
mNotification.setTicker("First Time");//通知首次出现在通知栏时的效果
mNotification.setNumber(5);//通知集合的数量
//var str = dateToStr(new Date());
//mNotification.setWhen(str);//通知产生时间
//mNotification.setContentIntent();//通知栏点击事件
mNotification.setDefaults(Noti.DEFAULT_VIBRATE);//声音、闪灯、震动效果,可叠加
mNotification.setPriority(Noti.PRIORITY_DEFAULT);//通知优先级
mNotification.flags=Notification.FLAG_ONLY_ALERT_ONCE;//发起通知时震动
var mNb = mNotification.build()
nm.notify(NotifyID , mNb);
}
两个参数分别代表通知内容和通知编号,其他设置已经在代码注释中说明。结合上一部分的代码,在接收到实时消息后,创建通知栏消息,代码修改如下:
var i=0;
//开启连接
function startConnection() {
hub.on('listen',function (message) {
$('#_messageList').append('' + message + '');
i=i+1;
CreateNotification(message,i);
});
listener.start().fail(function () {
$('#_messageList').append('打开连接失败! ');
}).done(function () {
$('#_messageList').append('连接已打开... ');
});
}
测试时使用了两部手机、一台服务器,均位于同一局域网内。后将服务端部署到公网测试服务器上,同样可用。必须将SignalR服务端启用跨域访问,否则无法实现功能。
作为一个会一点点JS的.NET程序员,只是实现了最基本的需求,后期还要继续实现点击通知打开应用等功能。欢迎大家前来探讨,不吝赐教!