消防培训 嵌入式开发,解决方案提供

SignalR在Xamarin Android中的使用

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。

    下面介绍一下本人在Android手机开发中的使用,开发编译环境使用Xamarin。手机作为一个客户端接入服务器。

     首先,在Xamarin中建立Android App,添加SignalR Client开发包,目前最新版本为2.2.0.0。

     然后,添加FireHub类。FireHub类的实现代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Hubs;

using NicoDemo.Model;

namespace Nico.Android.SignalR
{
	public class FireHub
	{
		#region 变量声明
		public HubConnection _connection=null;
		private IHubProxy _proxy=null;
		public bool IsConnected = false;
		public delegate void ReceiveMessageDelegate(string msg);
		public event ReceiveMessageDelegate Receive=null;
		public delegate void HubCloseDelegate();
		public event HubCloseDelegate CloseHub = null;
		public delegate void HubStatusChangedDelegate(int state,string msg);
		public event HubStatusChangedDelegate StateChanged = null;

		public delegate void AddWebMessageDelegate(WebMessage wm);
		public event AddWebMessageDelegate AddWebMessage = null;
		#endregion

		#region 初始化
		public FireHub()
		{
			IsConnected = false;
			_connection = null;
			_proxy = null;
		}

		public string Dispose()
		{
			try
			{
				if (_connection != null)
				{
					try
					{
						_connection.Stop();
					}
					catch
					{

					}
					_connection = null;
				}
				if (_proxy != null)
					_proxy = null;
				IsConnected = false;
				return "";
			}
			catch(Exception err)
			{
				return string.Format("({0}-{1})",err.Message + err.StackTrace);
			}
		}
		#endregion

		#region HUB事件
		void _connection_Closed()
		{
			if (CloseHub != null)
				CloseHub();
			IsConnected = false;
		}

		void _connection_Received(string obj)
		{
			if (Receive != null)
				Receive(obj);
		}
		#endregion

		#region HUB客户端方法

		public bool Connect(string url,int timeout=5000)
		{
			try
			{
				if (_connection == null)
				{
					_connection = new HubConnection(url);//,queryString);
					_connection.Received += _connection_Received;
					_connection.Closed += _connection_Closed;
					_connection.StateChanged += _connection_StateChanged;
					_proxy = _connection.CreateHubProxy("notifyHub");
				}
				if (_connection.Start().Wait(timeout))//同步调用
				{
					IsConnected = true;
					return true;
				}
				else
				{
					IsConnected = false;
					_connection.Dispose();
					_connection = null;
					_proxy = null;
					return false;
				}
			}
			catch
			{
				return false;
			}
		}

		void _connection_StateChanged(StateChange obj)
		{
			try
			{
				switch (obj.NewState)
				{
				case ConnectionState.Disconnected:
					IsConnected = false;
					if (_connection != null)
					{
						_connection.Dispose();
						_connection = null;
						_proxy = null;
					}
					if (StateChanged != null)
						StateChanged(0,"");
					break;
				}
			}
			catch(Exception err)
			{
				if (StateChanged != null)
					StateChanged(1, "_connection_StateChanged:"+err.Message);                
			}
		}

		public bool ConnectToServer(UsersEntity user,int timeout=5000)
		{
			try
			{
				if (_connection == null || _proxy == null||!IsConnected)
					return false;
				return _proxy.Invoke("connect",user.ID,user.Name,user.TypeID).Wait(timeout);
			}
			catch(Exception err)
			{
				if (StateChanged != null)
					StateChanged(1, "ConnectToServer:"+err.Message);                
				return false;
			}
		}

		public bool SendMessageToAll(UsersEntity user,string message, int timeout = 5000)
		{
			try
			{
				if (_connection == null || _proxy == null || !IsConnected)
					return false;
				_proxy.Invoke("sendMessageToAll", user.ID,user.Name,user.TypeID,message);//.Wait(timeout);
				return true;
			}
			catch(Exception err)
			{
				if (StateChanged != null)
					StateChanged(1,"SendMessageToAll:"+ err.Message);                
				return false;
			}
		}

		public bool SendMessageToPrivate(string toConnID, string message)
		{
			try
			{
				if (_connection == null || _proxy == null || !IsConnected)
					return false;
				_proxy.Invoke("sendPrivateMessage", toConnID, message);
				return true;
			}
			catch(Exception err)
			{
				if (StateChanged != null)
					StateChanged(1, "SendMessageToPrivate:"+err.Message);                
				return false;
			}
		}
		#endregion

		#region 公共函数
		public bool SendToWeb(UsersEntity user,int timeout=5000)
		{
			try
			{
				//        <th>事件时间</th>
				//<th>事件类型</th>
				//<th>发送者</th>
				//<th>单位编号</th>
				//<th>信息内容</th>
				if (!SendMessageToAll(user,"connect test", timeout))
					return false;
				return true;
			}
			catch (Exception err)
			{
				if (StateChanged != null)
					StateChanged(1, "SendToWeb:"+err.Message);
				return false;
			}
		}

		#endregion

	}

	public class HubUser
	{
		[DisplayName("连接ID")]
		public string ConnectionId { get; set; }

		[DisplayName("用户ID")]
		public int UserID { get; set; }

		[DisplayName("用户名")]
		public string UserName { get; set; }

		[DisplayName("用户类型")]
		public int TypeID { get; set; }

		[DisplayName("连入时间")]
		public DateTime ConnectionTime { get; set; }

		public HubUser(string connID,int userID, string name,int typeID)
		{
			ConnectionId = connID;
			UserID = userID;
			UserName = name;
			TypeID = typeID;
			ConnectionTime = DateTime.Now;
		}
	}

	public class WebMessage
	{
		public string ToConnID{get;set;}
		public DateTime MessageDate{get;set;}
		public string MessageContent { get; set; }
		public bool IsAnswer{get;set;}
		public int RepeatCounts { get; set; }
		public bool IsRemovable { get; set; }

		public WebMessage()
		{
			ToConnID=string.Empty;
			MessageDate=DateTime.Now;
			MessageContent = string.Empty;
			IsAnswer=false;
			RepeatCounts = 0;
			IsRemovable = false;
		}
	}
}

 最后,在Activity中增加对FireHub的使用,参考代码如下:

	public class SignalRActivity : Activity
	{
		private FireHub _fireHub = null;
                private UsersEntity _user = null;
		
                protected override void OnCreate (Bundle bundle)
		{
			base.OnCreate (bundle);

			// Create your application here
			SetContentView(Resource.Layout.SignalR);

			_user = new UsersEntity ();

			Button btnConnectHub = FindViewById<Button> (Resource.Id.btnConnectHub);
			btnConnectHub.Text = "监控网站连接";
			btnConnectHub.Click += btnConnectHubClick;
		}


		protected void btnConnectHubClick(object sender,EventArgs e)
		{
			try
			{
				if (_fireHub != null)
				{
					StopHub();
					lock (_syncUser)
					{
						_hubUser.Clear();
					}
					//UpdateList();
				}
				else
				{
					if (HubReconnect(false))
					{
						RunOnUiThread(new Action(()=>{ _txtView.Text=string.Format("{0}: 实时网站连接成功", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));}));
					}
					else
					{
						RunOnUiThread(new Action(()=>{ _txtView.Text=string.Format("{0}: 实时网站连接失败", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));}));						
					}
				}
			}
			catch (Exception err)
			{
				//FormMain.STAErrLogger.Write(string.Format("{0}({1}-{2})", err.Message, "FormMain", "btnConnectHub_Click"));
			}
		}


		#region HUB管理

		bool HubReconnect(bool checkNull=true)
		{
			bool bRet = false;
			bool isUpdate = false;
			//重新连接到服务网站
			if (!checkNull || _fireHub != null)
			{
				if (_fireHub != null)
					_fireHub.IsConnected = false;
				if (!ConnectHubServer())
				{

				}
				else
				{
					bRet = true;
				}
				isUpdate = true;
			}
			return bRet;
		}

		public bool ConnectHubServer()
		{
			try
			{
				if (_fireHub == null)
					_fireHub = new FireHub();
				else
				{
					if (_fireHub.IsConnected)
						return true;
				}
				if (!_fireHub.Connect("http://your service web", 5000))
				{
					RunOnUiThread(new Action(()=>{ _txtView.Text="实时报警服务网站不在服务状态";}));
					if (_fireHub != null)
					{
						string strDispose = _fireHub.Dispose();
						if (!string.IsNullOrEmpty(strDispose))
						{
							//FormMain.STAErrLogger.Write(string.Format("{0}({1})", "ConnectHubServer-0", strDispose));
						}
					}
					_fireHub = null;
					return false;
				}
				else
				{
					
					if (_fireHub.ConnectToServer(_user))
					{
						_fireHub.Receive -= _fireHub_Receive;
						_fireHub.Receive += _fireHub_Receive;
						_fireHub.CloseHub -= _fireHub_CloseHub;
						_fireHub.CloseHub += _fireHub_CloseHub;
						_fireHub.StateChanged -= _fireHub_StateChanged;
						_fireHub.StateChanged += _fireHub_StateChanged;
						_fireHub.AddWebMessage -= _fireHub_AddWebMessage;
						_fireHub.AddWebMessage += _fireHub_AddWebMessage;

						if (_webMessageManage == null)
						{
							_webMessageManage = new WebMessageManage();
							_webMessageManage.WebMessageCallback += _webMessageManage_WebMessageCallback;
						}
						RunOnUiThread(new Action(()=>{ _txtView.Text="成功连接到实时报警服务网站";}));
					}
					else
					{
						RunOnUiThread(new Action(()=>{ _txtView.Text="连接到实时报警服务网站失败,请重新尝试";}));
						string strDispose = _fireHub.Dispose();
						if(!string.IsNullOrEmpty(strDispose))
						{

						}
						_fireHub = null;
						return false;
					}
				}
				return true;
			}
			catch (Exception err)
			{

				return false;
			}
		}
		#endregion

		#region FireHub事件实现

		void _fireHub_Receive(string msg)
		{
			try
			{
				HubMessage hm = new HubMessage();
				hm = Newtonsoft.Json.JsonConvert.DeserializeObject<HubMessage>(msg);
				if (hm == null)
					return;
				if (hm.M == "onConnected")
				{
					#region 客户端连接成功后的反馈消息

					#endregion
				}
				else if (hm.M == "onNewUserConnected")
				{
					#region 有新的客户端接入

					#endregion
				}
				else if (hm.M == "onUserDisconnected")
				{
					#region 客户端断开

					#endregion
				}
				else if (hm.M == "messageReceived")
				{
					#region 定时广播巡查

					#endregion
				}
				else if (hm.M == "sendCallbackMessage")
				{
					#region 私人消息发出成功后,返回反馈消息

					#endregion
				}
				else if (hm.M == "sendPrivateMessage")
				{
					#region 接收到私人消息

					#endregion
				}
			}
			catch (Exception err)
			{
				RunOnUiThread(new Action(()=>{
					_txtView.Text="HUB Error:" + err.Message + err.Source;
				}));
			}
		}

		void _fireHub_CloseHub()
		{
			StopHub();
		}

		public void StopHub()
		{
			try
			{
				RunOnUiThread(new Action(()=>{
					_txtView.Text="实时报警服务网站关闭";
				}));
				if (_fireHub == null)
					return;
				string strDispose = _fireHub.Dispose();
				if (!string.IsNullOrEmpty(strDispose))
				{

				}
				_fireHub = null;
				RunOnUiThread(new Action(()=>{
					ChangeHubButtonStatus();
				}));
			}
			catch (Exception err)
			{

			}
		}

		void _webMessageManage_WebMessageCallback(int flag)
		{
			try
			{
				if (flag == 0)
				{
					if ((DateTime.Now - _dtHubReconnect).TotalMinutes < 30)
					{
						return;
					}
					RunOnUiThread(new Action(()=>{

					}));
					//重新连接到服务网站
					if(HubReconnect(true))
					{
						_dtHubReconnect = DateTime.Now;
					}
				}
			}
			catch (Exception err)
			{

			}
		}

		void _fireHub_AddWebMessage(WebMessage wm)
		{
			try
			{
				if (_webMessageManage != null)
				{
					_webMessageManage.AddMessage(wm);
				}
			}
			catch (Exception err)
			{

			}
		}

		void _fireHub_StateChanged(int state, string msg)
		{
			try
			{
				switch (state)
				{
				case 0://断开连接了
					{
						RunOnUiThread(new Action(()=>{
							_txtView.Text="HUB掉线";
						}));	
						StopHub();
					}
					break;
				case 1://HUB异常
					{
						RunOnUiThread(new Action(()=>{
							_txtView.Text=msg;
						}));		
						StopHub();
					}
					break;
				}
			}
			catch (Exception err)
			{

			}
		}

		#endregion

    }

      完成以后编译通过,并且能够实现服务器和客户端的实时消息推送。

posted @ 2015-10-18 09:01  沈府大厨  阅读(717)  评论(0编辑  收藏  举报
我们一直在努力,关注苏州国网