SignalR在Xamarin Android中的使用

原文: SignalR在Xamarin Android中的使用

    ASP.NET SignalR 是爲 ASP.NET 開發人員提供的一個庫,能夠簡化開發人員將實時 Web 功能添加到應用程序的過程。實時 Web 功能是指這樣一種功能:當所鏈接的客戶端變得可用時服務器代碼能夠當即向其推送內容,而不是讓服務器等待客戶端請求新的數據。html

    下面介紹一下本人在Android手機開發中的使用,開發編譯環境使用Xamarin。手機做爲一個客戶端接入服務器。web

     首先,在Xamarin中創建Android App,添加SignalR Client開發包,目前最新版本爲2.2.0.0。服務器

     而後,添加FireHub類。FireHub類的實現代碼以下:app

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的使用,參考代碼以下:ide

	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

    }

      完成之後編譯經過,而且可以實現服務器和客戶端的實時消息推送。函數

相關文章
相關標籤/搜索