17

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

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

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

这里的挑战是确定何时需要推送以及在何处启动流程,因此

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

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

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

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

非常感谢您的帮助。

4

2 回答 2

6

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

很抱歉这个回复,但你建议的所有 3 个解决方案都是可怕的黑客 ;-)。如果你想提出一个好的解决方案,你必须深入研究 XMPP 和 iOS。1 周是一个非常短的时间框架。

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

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

于 2013-04-19T07:26:09.573 回答
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];
于 2014-04-29T02:00:40.797 回答