向离线用户发送聊天推送通知到iOS设备,使用Openfire XMPP。

17
我有一个使用openfire的ios聊天应用程序,我需要在以下情况下发送推送通知:(1)消息无法传递,无论什么原因;(2)应用程序处于挂起状态,即不能自行生成通知。
我已经阅读了stackoverflow和其他地方的大部分相关问题/建议,并得出了我的问题的几个解决方案。我不是ios开发人员,也不知道openfire或xmpp在几天前之前的任何事情,所以我担心我的理解可能不完整,我的解决方案可能存在缺陷。
请确认我的理解并建议是否遗漏了某些内容或是否有更好的方法。请还建议关于实现下面列出的特定解决方案有多复杂。这里的挑战是确定何时需要推送以及在哪里启动该过程。
一种方法是使用xmpp的xep-0184实现来检查消息是否已传递。为此,我们应该在ios数据库中的消息中具有某个已传递标志,当接收到传递的响应时,该标志会更新。因此,我们需要在一段时间后检查此标志,如果传递状态为false,则使用消息启动推送过程。看起来是一个复杂的解决方案(等待响应..稍后检查标志..不是很令人印象深刻)
更直接的方法是在openfire中做一些事情,当openfire无法传递消息时,它将其存储在离线表中,我们可以在该部分进行拦截,并使用消息启动推送过程。这似乎是正确的方法,但我真的很害怕深入openfire并更改某些内容(这可能也很容易,曾经稍微使用过openfire的人可以说吗?)
这是我的最后一招,这不是一个解决方案..但如果我不能在预期时间内(即从现在开始的一周内)正确地完成它,我们计划为所有消息发送推送通知。oppenfire将负责正常聊天,而我们的服务器将为每个消息发送推送,但当应用程序处于前台时,我们会执行某些操作以处理不需要显示的额外推送消息,否则每当有消息时就会收到推送。你们认为这种临时解决方案如何(当然,我们必须尽快更改这种情况),这可行吗(还是我在这里遗漏了什么)?
P.S. 有人能告诉WhatsApp和其他流行应用程序如何处理这个问题吗?
非常感谢您的帮助。

感谢提到XEP-0184协议! - VinceFR
请参考以下链接:http://stackoverflow.com/questions/30253948/how-to-send-push-notification-to-offline-users-of-xmpp/30530294#30530294 - Parthpatel1105
2个回答

6
XMPP需要在整个XMPP会话期间保持持久的套接字连接或“持久”的BOSH连接。我认为您面临的挑战是iOS不允许您在后台运行应用程序和套接字。每当您的iOS应用程序进入后台时,iOS会关闭您的套接字连接,而您的Openfire服务器会关闭您的XMPP会话。这意味着用户变为离线状态。这也是为什么针对此用户的传入消息会进入离线存储的原因。
很抱歉,但您提出的所有3种解决方案都是可怕的hack。如果您想提出一个好的解决方案,您必须深入研究XMPP和iOS。1周对于这个来说非常短。
有人能告诉我WhatsApp和其他流行应用程序如何处理此问题吗?
他们保持XMPP会话处于活动状态。这仅适用于高度修改的XMPP服务器,一些“XMPP客户端代理”之间保持您的会话运行,同时您的应用程序在后台运行,或两者的组合。

谢谢Alex。据我所知,当应用程序被iOS暂停状态(在后台运行10分钟后)时,它不能再执行任何代码,但当它在后台运行时,应该能够内部接收消息并生成通知(非推送)。你是说这不可能吗?我完了!:( ...所以,对于WhatsApp,iOS也必须关闭套接字连接,但正如你所说,他们通过XMPP客户端代理来处理它?是吗? - shailesh
请在此处阅读有关iOS应用程序状态的内容: http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html - Alex
6
Alex回答错误了。Whatsapp使用服务器来跟踪用户离线时的信息,并使用推送通知。你不能让应用程序永远保持在线状态。 - DivineDesert
如何在我离线时从我的Openfire服务器向我发送推送通知 - Sri..
@DivineDesert 你能告诉我如何管理或编写服务器端的离线(推送)通知吗?也就是说,当服务器端知道对方没有收到消息时,我们必须向他/她传递推送通知...而对方用户处于离线状态? - Dhaval Bhadania
显示剩余8条评论

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];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接