向特定用户或设备推送通知

Posted

技术标签:

【中文标题】向特定用户或设备推送通知【英文标题】:Push notifications to specific users or devices 【发布时间】:2018-10-30 23:22:35 【问题描述】:

我有一个 WEB MVC 5 系统,在该系统中我使用 signalR 和 SqlDependency 进行实时处理,但这不是我需要实施的情况,而是在感兴趣的更改时向系统管理员推送通知。具体来说,我需要一种向特定用户发送推送通知的机制,如果可能的话,即使他们没有连接,也就是说,即使他们没有使用系统。

我搜索了很多,我使用的是 push.js 库,但这不允许我这样做,或者我认为是这样。

任何可以提供满足我需求的机制或类似的东西都会被接收。

【问题讨论】:

我在 1 年前实施了一个您需要帮助的类似程序。我正在向连接的用户发送通知。我可以将代码发送给您,但首先,我需要根据您的需要重新排列。 谢谢,但是您可以选择通知哪些用户吗? 我可以选择要推送通知的用户,你能提供你为此编写的代码吗。 你有什么方法可以帮助我解决我的问题吗? 你看我的回答了吗? 【参考方案1】:

我编写了一个存储过程(SP),它根据用户返回事件详细信息。您可以创建一个表来保存您要发送通知的 ID,并且每次插入此表都会通知用户。

我有三个表,分别是“用户”、“事件”、“用户事件”。 在 UserEvents 表中有 userID 作为用户表的外键和 eventID 作为事件表的外键。在我的系统中,当事件插入到上面的表中时,signalR 会完成它的工作。 UserEvents 表有如下列:

   [Uev_ID]
  ,[Uev_UserID]
  ,[Uev_EventID]
  ,[Uev_IsRead]
  ,[Uev_ReadDate]
  ,[GuID]
  ,[Deleted]

我的事件模型如下:

    public class EventList
    
    public Int64 EventID  get; set; 
    public string Title  get; set; 
    public string Description  get; set; 
    public DateTime Date  get; set; 
    public string Color  get; set; 
    

应该有一个消息存储库来与数据库和模型进行交互和通信。此存储库将处理dependency_OnChange 方法。

    public class MessagesRepository
    
    internal static SqlCommand command = null;
    internal static SqlCommand command2 = null;
    internal static SqlDependency dependency = null;
    internal static SqlDependency dependency2 = null;
    readonly string _connString = 
                  ConfigurationManager.ConnectionStrings["signalr"].ConnectionString;
    private Int64 user  get; set; 
    public MessagesRepository(Int64 userID)
    
        user = userID;
    

    public IEnumerable<EventList> GetAllMessages()
    
        var messages = new List<EventList>();
        using (var connection = new SqlConnection(_connString))
        
            connection.Open();
            using (command = new SqlCommand("[sp_SysEvent]", connection))
            
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddWithValue("@user", user);
                command.Notification = null;

                if (dependency == null)
                
                    dependency = new SqlDependency(command);
                    dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
                
                if (connection.State == ConnectionState.Closed)
                    connection.Open();

                var reader = command.ExecuteReader();

                while (reader.Read())
                
                    messages.Add(item: new EventList  EventID = (Int64)reader["Evt_ID"], Description = (string)reader["Evt_Description"], Title = (string)reader["Evg_Title"], Date = (DateTime)reader["Evt_Date"], Color = (string)reader["Clr_Color"] );
                
            
        
        return messages;
    

    private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    
        if (dependency != null)
        
            dependency.OnChange -= dependency_OnChange;
            dependency = null;
        
        if (e.Info == SqlNotificationInfo.Insert)
        

            TestHub.SendUser(user);
        
    

我需要一个连接映射文档来向连接的用户发送通知。当用户连接时,我将其 ID 放入 HashSet 并在用户断开连接时从 HashSet 中删除。您可以使用它来检测连接的用户。 这是连接映射: 公共类连接映射 私人词典> _connections = 新词典>();

    public int Count
    
        get
        
            return _connections.Count;
        
    


    public void Add(T key, string connectionId)
    
        lock (_connections)
        
            HashSet<string> connections;
            if (!_connections.TryGetValue(key, out connections))
            
                connections = new HashSet<string>();
                _connections.Add(key, connections);
            

            lock (connections)
            
                connections.Add(connectionId);
            
        
    

    public IEnumerable<string> GetConnections(T key)
    
        HashSet<string> connections;
        if (_connections.TryGetValue(key, out connections))
        
            return connections;
        

        return Enumerable.Empty<string>();
    
    //public IEnumerable<string> GetConnections2(T key)
    //
    //    List<HashSet<string>> connections;
    //    if (_connections.Any(x => x.Key.ToString().Contains(key.ToString())))
    //    
    //        connections = _connections.Where(x => x.Key.ToString().StartsWith(key.ToString() + "_")).Select(x => x.Value);
    //    

    //    return Enumerable.Empty<string>();
    //
    public void Remove(T key, string connectionId)
    
        lock (_connections)
        
            HashSet<string> connections;
            if (!_connections.TryGetValue(key, out connections))
            
                return;
            

            lock (connections)
            
                connections.Remove(connectionId);

                if (connections.Count == 0)
                
                    _connections.Remove(key);
                
            
        
    

Hub 文档是:

public class TestHub : Hub

    private readonly static ConnectionMapping<string> _connections = new ConnectionMapping<string>();
    public string GetUserGroup()
    
        string abc = "";
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["signalr"].ConnectionString))
        
            connection.Open();
            string sqltheme = "Select Usr_GroupID from SysUser where ID=" + Convert.ToInt32(HttpContext.Current.User.Identity.Name.Split('_')[1]) + "";
            using (SqlCommand command = new SqlCommand(sqltheme, connection))
            
                abc = command.ExecuteScalar().ToString();
            
        
        return abc;
    
    public override Task OnConnected()
    
        string name = "";
        try
        
            name = HttpContext.Current.User.Identity.Name.Split('_')[1];
            Groups.Add(Context.ConnectionId, GetUserGroup());
        catch(Exception ex)
        
            name = Context.ConnectionId;
        
        if (_connections.GetConnections(name).Count() > 0)
        
            _connections.Remove(name, _connections.GetConnections(name).ToString());
        
        _connections.Add(name, Context.ConnectionId);
        return base.OnConnected();
    
    [HubMethodName("send")]
    public void Send(string mes)
    
        Clients.All.send(mes); // if you want to send all user use this.
    
    [HubMethodName("sendUser")]
    public void SendUser(string[] who, int id, string title)
    
        string name = Context.User.Identity.Name;
        foreach (var user in who)
        
            foreach (var connectionId in _connections.GetConnections(user))
            
                Clients.Client(connectionId).sendUser(id, title);
            
        
    
    

最后,调用 hub 函数的 javascript 代码:

var myhub = $.connection.testHub;
        $(function () 
            $.connection.hub.start();
            chat.client.sendUser = function (id, title) 
                var count = parseFloat($("#header_notification_bar > a > span").text()) + 1;
                $("#header_notification_bar > a > span").text(count);
                toastr.info('Bir Yeni Bildiriminiz Var.Görüntülemek İçin Tıklayınız.', 'Bildirim', 
                    closeButton: true, timeOut: 20000, onclick: function () 
                        window.location.href = '/tr/Notification/List';
                    
                );
                $("#notification_list").prepend("<li><a href='javascript:;' style='background-color:#e6e6e6' class='okunmadi' id='" + id + "'><span class='time' style='min-width:100px;'>şimdi</span><span class='details'><span class='label label-sm label-icon label-success'><i class='fa fa-bullhorn'></i></span>" + title + "</span></a></li>");
            ;

我希望它也对你有用。

【讨论】:

以上是关于向特定用户或设备推送通知的主要内容,如果未能解决你的问题,请参考以下文章

如何在特定时间从 iOS 通知中心自动删除推送通知?

如何在通知中心向特定用户发送推送通知?

如何收集特定令牌以向特定设备发送推送通知

如何在 iOS 中使用 Google Firebase 向特定用户发送推送通知?

使用 OneSignal 推送通知服务向特定测试设备发送推送通知

向知道电话号码的特定设备发送推送通知,parse.com