向 ios 发送推送通知以与离线用户聊天,openfire xmpp

Posted

技术标签:

【中文标题】向 ios 发送推送通知以与离线用户聊天,openfire xmpp【英文标题】:send push notification to ios for chat to offline user, openfire xmpp 【发布时间】:2013-04-12 09:33:30 【问题描述】:

我有一个使用openfire的ios聊天应用程序,我需要做的是在消息(1)由于任何原因无法传递,(2)应用程序处于暂停状态时发送推送通知,即不能自行生成通知。

我已经阅读了关于 *** 和其他地方的大部分相关问题/建议,并且我得出的解决方案很少。我不是ios开发人员,前几天对openfire或xmpp一无所知,所以我担心我对事物的理解可能不完整,我的解决方案可能存在缺陷。

请确认我对它的理解,并建议我是否遗漏了什么或者是否有更好的方法。还请就实施下列特定解决方案的复杂程度提出建议。

这里的挑战是确定什么时候需要推送,以及在哪里启动流程,所以

1) 一种方法是使用 xmpp 的 xep-0184 实现来检查消息是否已传递。为此,我们应该在 ios 数据库中有一些带有消息的传递标志,当从另一端接收到传递的响应时更新。所以我们需要在一段时间后检查这个标志,如果传递状态为假,则使用消息启动推送过程。看起来是一个复杂的解决方案(等待响应..检查标志有一些时间延迟..不是很令人印象深刻)

2) 更直接的方法是在 openfire 中做一些事情,当 openfire 无法传递消息时,它会将其存储在离线表中,我们可以对该部分进行一些拦截并使用消息启动推送过程。这看起来是正确的方法,但我真的很害怕在 openfire 中得到那么多并改变一些东西(这也可能很容易,用过 openfire 的人可以告诉我们吗?)

3) 这是我最后的手段,这不是一个解决方案。但如果我不能在预期的时间范围内(现在是一周后)正确地做到这一点,我们计划为所有消息。 oppenfire 会处理正常的聊天,而我们的服务器会为每条消息发送一个推送,但是当应用程序处于前台时,我们会做一些事情来处理不需要显示的额外推送消息,否则只要有一个推送就会收到信息。你们如何看待这种临时的方法(我们当然必须尽快改变它),这是否可行(或者我在这里也遗漏了一些东西)。

附:谁能告诉 Whatsapp 和其他流行的应用程序是如何处理这个问题的?

非常感谢您的帮助。

【问题讨论】:

感谢提及 xep-0184 协议! 参考此链接***.com/questions/30253948/… 【参考方案1】:

XMPP 在整个 XMPP 会话期间需要持久的套接字连接或“持久的”BOSH 连接。我认为您的挑战是 iOS 不允许您在后台运行您的应用程序和套接字。每当您的 iOS 应用程序进入后台时,iOS 都会终止您的套接字连接,并且您的 Openfire 服务器会终止您的 XMPP 会话。这意味着用户离线。这也是该用户的传入消息进入离线存储的原因。

对此回复感到抱歉,但您建议的所有 3 个解决方案都是可怕的 hack ;-)。如果你想提出一个好的解决方案,你必须深入研究 XMPP 和 iOS。 1 周的时间很短。

谁能告诉 Whatsapp 和其他流行的应用程序是如何处理这个问题的?

它们使 XMPP 会话保持活动状态。这仅适用于经过高度修改的 XMPP 服务器,它们之间的一些“XMPP 客户端代理”可以在您的应用程序处于后台时保持会话运行,或两者兼而有之。

【讨论】:

谢谢亚历克斯。到目前为止我所了解的,当应用程序被 ios 置于挂起状态时(在后台运行 10 分钟后),它不能再执行任何代码,但是当它在后台时,应该能够接收消息并在内部生成通知(不是推送)。你说这不可能??我死了!! :( ...所以,对于whatsapp,ios也必须终止套接字连接,但正如你所说,他们正在通过xmpp客户端代理处理它?对吧? 请在此处阅读有关 iOS 应用状态的信息:developer.apple.com/library/ios/#documentation/iphone/… @Alex 错误答案,Whats 应用程序使用服务器来跟踪用户何时离线并使用推送通知,你不能让你的应用程序永远存在 当我在我的 openfire 服务器上离线时如何从服务器发送推送通知 @DivineDesert 嘿,你能告诉如何从服务器端离线管理或编码(推送)通知意味着当服务器端知道对方没有收到消息,所以我们必须通过推送通知他/她......而对方用户离线?【参考方案2】:

我有一个解决方案。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    self.ary_UserStatus = [NSMutableArray array];
    NSMutableArray *ary_TempFromUserDefaults = [NSMutableArray array];
    ary_TempFromUserDefaults = [[NSUserDefaults standardUserDefaults] valueForKey:@"KejdoUserStatus"];

    if ([ary_TempFromUserDefaults count]>0)
    
         self.ary_UserStatus = [[NSUserDefaults standardUserDefaults]    valueForKey:@"KejdoUserStatus"];
       

      self.df_UserStatus = [[NSDateFormatter alloc] init];
      [self.df_UserStatus setDateFormat: @"hh:mm a MM/dd/yyyy"];


- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence

    DDLogVerbose(@"%@: %@ - %@", THIS_FILE, THIS_METHOD, [presence fromStr]);

    NSString *str_UserName = [[presence from] user];
    NSString *str_LastSeenDate = [self.df_UserStatus stringFromDate:[NSDate date]];
    NSMutableDictionary *mdic_UserPresence = [[NSMutableDictionary alloc] init];

    [mdic_UserPresence setValue:str_UserName forKey:@"Name"];
    [mdic_UserPresence setValue:str_LastSeenDate forKey:@"Date"];
    [mdic_UserPresence setValue:[presence type] forKey:@"Type"];

    if ([self.ary_UserStatus count]>0)
    
        int index;
        BOOL IS_exist=FALSE;
        for (int i=0; i<[self.ary_UserStatus count]; i++)
        
            NSString *str_UserFromArray = [[self.ary_UserStatus objectAtIndex:i] valueForKey:@"Name"];
            if ([str_UserName isEqualToString:str_UserFromArray])
            
                IS_exist = TRUE;
                index = i;
                [[NSUserDefaults standardUserDefaults] setObject:str_UserName forKey:@"Status"];
            
            else
            
            

        
        if (IS_exist) 
            [self.ary_UserStatus replaceObjectAtIndex:index withObject:mdic_UserPresence];
        
        else
        
            [self.ary_UserStatus addObject:mdic_UserPresence];
        
    
    else
    
        [self.ary_UserStatus addObject:mdic_UserPresence];
    


    [[NSUserDefaults standardUserDefaults] setObject:self.ary_UserStatus forKey:@"KejdoUserStatus"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"UserStatusChangeNotification" object:self];


无论您在聊天中向其他用户发送消息的任何位置。这样做

 if(appDelegate.ary_UserStatus.count>0)
    
     for (int i=0; i<[appDelegate.ary_UserStatus count]; i++)
     
      if ([jid.user isEqualToString:[NSString stringWithFormat:@"%@",[[appDelegate.ary_UserStatus objectAtIndex:i] valueForKey:@"Name"]]])
        
         if ([[[appDelegate.ary_UserStatus objectAtIndex:i] valueForKey:@"Type"] isEqualToString:@"available"])
           
                                // Do something like table reload.
                                break;
             
               else
                    [self sendPushNotification];
           
         
       
        else
            [self sendPushNotification];

【讨论】:

以上是关于向 ios 发送推送通知以与离线用户聊天,openfire xmpp的主要内容,如果未能解决你的问题,请参考以下文章

设备离线时,apns 丢弃了旧的推送通知

用户离线时Openfire发送推送通知

是否可以在 ios 中自定义推送通知屏幕?

苹果推送通知问题

Parse.com - 从 Parse.com 向 iOS 应用程序发送消息,不像推送通知

Quickblox“离线用户的自动推送通知”不起作用