SignalR在Xamarin Android中的使用

简介: 原文:SignalR在Xamarin Android中的使用    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。
原文: 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

    }

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

目录
相关文章
|
6月前
|
开发工具 Android开发 iOS开发
使用xamarin开发Android、iOS报错failed to open directory: 系统找不到指定的文件
使用vs2019学习xamarin时,创建新程序。使用模拟器真机等测试都报错如下图错误: ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/column/article/5877188/20231030-de8ce5fd.png?x-cos-security-token=r4KyZDEowPT0kGTL0LqE8EnwfN1Nzexadb05dcffed3939ff8d7591c528c01706nvpGSE93QwHpZM8NwhJNTZctNRQa0l3KDhEnqj8P7d8t
63 0
使用xamarin开发Android、iOS报错failed to open directory: 系统找不到指定的文件
|
Java C# Android开发
.NET(WinCE、WM)开发转Android开发 ——Xamarin和Smobiler对比
WinCE从1995年诞生至今,已有20多年的发展历史,行业成熟方案覆盖范围广,从车载、工控、手持机都有涉及,且方案成熟。 近些年,Android以后来居上的态势,逐渐渗透至各行业领域,硬件手持大厂也把产品线重心向Android手持迁移,基于Android的行业解决方案越来越成熟,WinCE的开发人才流失,在WinCE解决方案上吃老本的企业寻求转型。
|
Web App开发 测试技术 Android开发
xamarin开发android收集的一些工具
原文:xamarin开发android收集的一些工具 xamarin开发android收集的一些工具 工欲善其事,必先利其器,从16年下半年开始做xamarin相关的开发,平时使用的一些工具和google插件给大家分享一下,都有下载地址,持续更新。
1485 0
|
Web App开发 JSON API
Xamarin android 调用Web Api(ListView使用远程数据)
xamarin android如何调用sqlserver 数据库呢(或者其他的),很多新手都会有这个疑问。xamarin android调用远程数据主要有两种方式: 在Android中保存数据或调用数据库可以利用SQLite,android中提供了几个类来管理SQLite数据库,对数据进行增删改查 直接调用Asp.net Web API对数据进行增删改查 这两种方式到底选择哪一种方式好一点呢?哪一种方式好不好我不敢确定,市场上大部分app都是调用api来clud的。
1302 0
|
Android开发 数据格式 XML
Xamarin Android Gestures详解
通过Gesture的监听我们将实现一个,手指的快速滑动显示坐标的变化,我们先来看一看效果图: 1.Android中手势交互的执行顺序 1.手指触碰屏幕时,触发MotionEvent事件! 2.
1001 0
|
Android开发 Java 数据格式
Xamarin Android自定义文本框
xamarin android 自定义文本框简单的用法 关键点在于,监听EditText的内容变化,不同于java中文本内容变化去调用EditText.addTextChangedListener(mTextWatcher);为EditText设置内容变化监听! 简单来说就是添加一个AfterTextChanged 事件就OK了,这是最简单的一种做法,当然你要想java那样去监听也可以的。
1142 0
|
缓存 Android开发 数据格式
xamarin android viewpager的用法
1.什么是ViewPager 通过手势滑动可以完成view的切换,一般是用来app的引导页或则实现图片轮播,类似网页上的banner轮播. Adnroid 3.0后引入的一个UI控件,在xamarin android 的开发中必须引入v4兼容包(ps这里有坑,菜鸟需要注意) 和ListVie...
1182 0
|
Android开发
xamarin android listview的用法
listview也许是用的非常频繁的一个控件之一,下面我写一个xamarin的listview栗子,大家尝一尝xamarin android开发的乐趣。原谅我的大小写吧. listview绑定自定义的BaseAdapter 先来看一下最终实现的效果图: News.
996 0
|
Android开发 Java
xamarin android如何监听单击事件
在xamarin android单击事件是最基础的事情,看过菜鸟上的android教程时,java写的都是监听事件,为一个按钮,单选按钮、多选按钮的单击事件有三种,前面两种用的非常普遍,也很简易,我这里主要就是写一下xamarin android中的监听事件。
1111 0
|
Android开发 数据格式 XML
xamarin android checkbox自定义样式
xamarin android checkbox自定义样式 在drawable文件在新建checkbox_bg.xml文件 //状态为选中 //状态为没选中 //默认的必须的有一个 在values文件夹中新建一个Style.
1264 0