SignalR在Xamarin Android中的使用

原文: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

    }

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

时间: 2024-08-04 06:32:18

SignalR在Xamarin Android中的使用的相关文章

Xamarin.Android中使用android:onClick=&quot;xxx&quot;属性

原文:Xamarin.Android中使用android:onClick="xxx"属性 在原生Android开发中,为一个View增加点击事件,有三种方式: 1.使用匿名对象 ((ImageButton) findViewById(R.id.music_cover)) .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); 我们知道,View.OnCl

Xamarin Android中引用Jar包的方法

新建一个Java Bingdings Library 将Jar包复制,或使用添加已存在的文件,到Jars文件夹中 确认属性中的"生成操作" 如果有类型转换不正确,请修改Transforms文件夹中的相应转换文件   之后编译此项目,在Android项目中引用 即可

Xamarin.Android 如何使用Assets目录下的文件

原文:Xamarin.Android 如何使用Assets目录下的文件 个人原创,转载注明出处:http://blog.csdn.net/supluo/article/details/43672411 Xamarin.Android  官网介绍地址:http://developer.xamarin.com/guides/android/application_fundamentals/resources_in_android/part_6_-_using_android_assets/ 这里插入

Xamarin.Android开发实践(六)

原文:Xamarin.Android开发实践(六) Xamarin.Android通知详解 一.发送通知的机制 在日常的app应用中经常需要使用通知,因为服务.广播后台活动如果有事件需要通知用户,则需要通过通知栏显示,而在Xamarin.Android下的通知需要获取NotificationManager服务,而该服务需要通过GetSystemService获取,同时还要传递一个标识符.获取了通知管理器后我们就可以实例化Notification,然后再由NotificationManager发送

Visual Studio跨平台开发实战(5) - Xamarin Android多页面应用程式开发

原文 Visual Studio跨平台开发实战(5) - Xamarin Android多页面应用程式开发 前言 大部份的Andr​​oid 都具有实体或虚拟的Back键. 因此在处理多页面应用程式时, 与先前所介绍的iOS Navigation controller 比较起来会简单许多. 1. 开启Visual Studio 并新增Android Application 专案并命名为Lab4-MultiScreen   2. 在Layout资料夹中新增Second.axml   在Second

Xamarin.Android开发实践(十八)

原文:Xamarin.Android开发实践(十八) Xamarin.Android之SlidingMenu 一.前言 有位网友在评论中希望能够出个在Xamarin.Android下实现SlidingMenu效果的随笔,刚好昨天在观看官网示例项目的时候也看到这个SlidingMenu,但是最终的效果并不是我们所期待的,至此笔者就在官方的论坛中寻找,最后也成功的寻找到的答案,下面笔者将带领带领大家实现SlidingMenu.   二.准备工作 实现SlidingMenu重点是需要一个第三方的类库,

Xamarin.Android开发实践(九)

原文:Xamarin.Android开发实践(九) Xamarin.Android之ActionBar与菜单 一.选项卡 如今很多应用都会使用碎片以便在同一个活动中能够显示多个不同的视图.在 Android 3.0 以上的版本中,我们已经可以使用ActionBar提供的Tab来实现这种效果,而不需要我们自己去实现碎片的切换.ActionBar默认是不具备选项 卡功能的,所以我们需要给一个属性赋上对应的枚举,比如下面的方式将开启选项卡. 1 ActionBar.NavigationMode = A

Xamarin.Android开发实践(十四)

原文:Xamarin.Android开发实践(十四) Xamarin.Android之ListView和Adapter 一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xamarin去实现它,以及如何使用适配器和自定义适配器(本文中的适配器的主要内容就是将原始的数据转换成了能够供列表控件显示的项).   二.简介适配器 在开始之前我们需要先了解下适配器,首先是提供给我们使用的适配器之间的关系: 下面我们将上面的适配器进行简单的介绍: BaseAdapter:顾名思义,就是

Xamarin.Android开发实践(十七)

原文:Xamarin.Android开发实践(十七) Xamarin.Android之定位 一.前言 打开我们手中的应用,可以发现越来越多的应用使用了定位,从而使我们的生活更加方便,所以本章我们将学习如何在Xamarin中进行定位的开发.     二.准备工作 因为我们的虚拟机是运行在电脑本地的,自然就没法进行定位了,但是我们可以借助DDMS这个工具帮助我们去调试.   首先要确定你的Android SDK所在的目录,读者可以通过以下方式找到: 工具->选项   然后读者打开该文件夹下的tool