[英]Send message to SignalR hub from any Xamarin (Visual Studio 2017) android activity
I've been able to create and receive messages from a SignalR hub from a html page, aspx page and an Xamarin client which is the app I really need it for using Microsoft.AspNet.SignalR.Client v2.4.1 using Xamarin in Visual Studio 2017. Once my Xamarin app authenticates the user I start the connection to the hub, next I wire up an event to receive messages. 我已经能够从HTML页面,aspx页面和Xamarin客户端创建并接收来自SignalR集线器的消息,这是我真正需要的应用程序,以便在Visual Studio中使用Xamarin来使用Microsoft.AspNet.SignalR.Client v2.4.1 2017年。一旦我的Xamarin应用验证了用户身份后,我便开始与集线器的连接,接下来我组织一个活动来接收消息。 All of this works just fine and I can receive messages in the android app no matter what activity is the current activity thanks to the event that is wired up.
所有这些工作都很好,而且由于连接了事件,无论当前活动是什么活动,我都可以在android应用程序中接收消息。 Now that I have this working I want to be able to send a message from the client to the hub without creating another connection to the hub.
现在,我已经完成了这项工作,我希望能够从客户端向集线器发送消息,而无需创建与集线器的其他连接。 I've looked at static classes, but cannot get that to work.
我看过静态类,但无法正常工作。 My code is:
我的代码是:
This is the code that is executed after the user is authenticated: 这是验证用户身份后执行的代码:
// Start SignalR connection
Client client = new Client(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
await client.Connect();
// Wire up the message received event
client.OnMessageReceived += (sender2, message) => RunOnUiThread(() => showMessage(message));
From here the user can navigate from view to view and is able to receive messages from the hub via the event and the showMessage
method. 用户可以在此处从一个视图浏览到
showMessage
视图,并能够通过事件和showMessage
方法从中心接收消息。 This all works flawlessly. 所有这些都完美无缺。
My Client Code: This code was copied from a stack overflow working example, I modified it to my requirements. 我的客户代码:此代码是从堆栈溢出工作示例复制而来的,我将其修改为我的要求。
namespace ChatClient.Shared
{
class Client
{
private readonly string _platform;
private readonly HubConnection _connection;
private readonly IHubProxy _proxy;
public event EventHandler<string> OnMessageReceived;
public Client(string platform, string username)
{
string _username = "username=" + username;
_platform = platform;
_connection = new HubConnection("https://Example.com/SignalRhub", _username);
_proxy = _connection.CreateHubProxy("chathub");
}
public async Task Connect()
{
await _connection.Start(); _proxy.On("broadcastMessage", (string platform, string message) =>
{
if (OnMessageReceived != null)
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
});
Send("Connected");
}
public async Task<List<string>> ConnectedUsers()
{
List<string> Users = await _proxy.Invoke<List<string>>("getConnectedUsers");
return Users;
}
public Task Send(string message)
{
return _proxy.Invoke("Send", _platform, message);
}
}
}
Now what I need to do is send a message to the hub using the connection created just after the logon to be distributed to all connected users. 现在,我需要使用登录后立即创建的连接向集线器发送消息,以将其分发给所有连接的用户。 I cannot figure out how to do that, I've tried using a static class and attempted to use methods I've found on the web, but nothing seems to work.
我无法弄清楚该怎么做,我尝试使用静态类并尝试使用在网络上找到的方法,但似乎没有任何效果。
My Hub code: 我的中心代码:
public class ChatHub : Hub
{
private static readonly List<User> Users = new List<User>();
public override Task OnConnected()
{
string userName = Context.QueryString["username"];
string firstname = Context.QueryString["firstname"];
string lastname = Context.QueryString["lastname"];
string connectionId = this.Context.ConnectionId;
var user = new User();
user.Name = userName;
user.ConnectionIds = connectionId;
try
{
Users.Add(user);
}
catch (Exception ex)
{
var msg = ex.Message;
}
// send list of connected users to client as a test
Send("Welcome " + userName, "Connected users are:");
foreach (var display in Users)
{
Send("",display.Name.ToString());
}
// test sending to a specific user
SendOne(connectionId, userName, "This is to a specific user.");
return base.OnConnected();
}
public override Task OnDisconnected(bool stopped)
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var item = Users.Find(x => x.ConnectionIds == connectionId);
Send(item.Name , " disconnected.");
Users.Remove(item);
return base.OnDisconnected(true);
}
public void SendOne(string connectionId, string userName, string message)
{
Clients.Client(connectionId).broadcastMessage(userName, message);
}
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public List<string> getConnectedUsers()
{
List<string> UserNames = new List<string>();
foreach (var ConnectedUser in Users)
{
UserNames.Add(ConnectedUser.Name );
}
return UserNames;
}
}
There are a lot of other things I will be doing in the hub, but for now I need to get the client to send messages without creating another connection 我将在集线器中做很多其他事情,但是现在我需要让客户端发送消息而不创建另一个连接
Is there a way I can access the connection created after the user is authenticated in other views/activities? 在其他视图/活动中对用户进行身份验证之后,是否可以访问我创建的连接?
* Update * *更新*
I changed my code in accordance with Leo Zhu's answer below, however I get an error when I try to instantiate the class on the line: 我根据下面的Leo Zhu的答案更改了代码,但是当我尝试实例化该类时,我得到了一个错误:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
GetInstance does not exist
when it actually does. GetInstance does not exist
。 No idea why it isn't "found". 不知道为什么它没有被“发现”。
* Update * *更新*
Removed the new
keyword from the line: 从该行中删除了
new
关键字:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
It now reads: 现在显示为:
Client client = Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
Works like a charm. 奇迹般有效。
Or you can try the singleton pattern,for example (Just to provide ideas,you need to code to your own needs): 或者,您也可以尝试使用单例模式(例如,提供想法,您需要根据自己的需要进行编码):
public sealed class Client
{
// A private constructor to restrict the object creation from outside
private Client()
{
...
}
// A private static instance of the same class
private static Client instance = null;
public static Client GetInstance()
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Client();
}
// Otherwise return the already existing instance
return instance;
}
}
then you could call by Client.GetInstance();
那么您可以通过
Client.GetInstance();
调用Client.GetInstance();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.