send push notification to ios for chat to offline user, openfire xmpp

11,399

Solution 1

XMPP requires a persistent socket connection or a "persistent" BOSH connection during your whole XMPP session. I think your challenge is that iOS does not allow you to run your app and socket in background. Whenever your iOS app goes in background iOS kills your socket connection, and your Openfire server kills your XMPP session. This means the user goes offline. Which is also the reason why incoming messages for this user go to the offline storage.

Sorry for this response, but all 3 solutions you suggested are terrible hacks ;-). If you want to come up with a good solution you have to go very deep into XMPP and iOS. 1 week is a very short timeframe for this.

Can anyone tell how Whatsapp and other popular apps handle this?

They keep the XMPP session alive. This works only with highly modified XMPP servers, some "XMPP Client Proxy" in between which keeps your session running while your app is in background, or a combination or both.

Solution 2

I have a solution for you.

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

}

And wherever you are sending message to other user in chat. Do this

 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];
Share:
11,399
shailesh
Author by

shailesh

Updated on June 14, 2022

Comments

  • shailesh
    shailesh about 2 years

    I have an ios chat application that uses openfire, what I need to do is send push notification when the message (1) can't be delivered for any reason, (2) app is in suspended state, i.e. can't generate a notification on its own.

    I have read most of the related questions/suggestions on this on stackoverflow and elsewhere and I have concluded few solutions to my problem. I am not an ios developer nor did I know anything about openfire or xmpp before a couple of days, so I am afraid my understanding of things may not be complete and my solutions might be flawed.

    Kindly confirm my understanding of it and suggest if I am missing something or if there is a better approach. Please also suggest about how complex it is going to be to implement a particular solution listed below.

    Challenge here is to identify when the push is required and where the process be initiated, so

    1) one way is to use the xep-0184 implementation of xmpp to check if the message is delivered. to do this we should have some delivered flag with message in ios database, which is updated when the delivered response is received form other end. So we need check for this flag after a little while and if the delivered status is false, initiate push process with the message. Looks to be a complicated solution (wait for response.. check flag with some time lag.. not very impressive)

    2) A more straight forward approach is to do something in openfire, when openfire can't deliver a message it stores it in offline table, we can do some interception on that part and initiate the push process with the message. This looks to be the correct approach but I am really afraid of getting that much inside openfire and change something(It might be easy also, somebody who has worked a little with openfire can tell?)

    3) This is my last resort, and this is not a solution.. but if I can't do it correctly within expected timeframe (which is a week from now) , We plan to send a push notification for all the messages. oppenfire will takecare of normal chat while a push will be sent from our server for each message but when the app is in foreground, we do something to handle the extra push messages that need not be shown, otherwise a push is received whenever there is a message. What do you guys think of this temporary way around (we will of course have to change this as soon as we can), is this doable (or I am missing something here as well).

    P.S. Can anyone tell how Whatsapp and other popular apps handle this?

    Many thanks for your help.

  • shailesh
    shailesh about 11 years
    Thanks Alex. As much I had understood so far, when the app is put in suspended state by ios (after 10 mins of running in background) , it can't execute any more codes, but when it is in background, should be able to receive message and generate notifications internally (not push). Are you saying this is not possible ?? i am dead!! :( ...so, for whatsapp also ios must be killing the socket connection, but as u said, they are handling it by xmpp client proxy? right?
  • Alex
    Alex about 11 years
    Please read here about the iOS app states: developer.apple.com/library/ios/#documentation/iphone/…
  • DivineDesert
    DivineDesert almost 11 years
    @Alex Wrong Answer, Whats app use server for tracking when user is offline and use push notification, you cant keep ur app live forever
  • Sri..
    Sri.. over 10 years
    How to sent pushonotification from server when i offline on my openfire server
  • Dhaval Bhadania
    Dhaval Bhadania over 9 years
    @DivineDesert hey can you tell how to manage or code from server side offline (push ) notification means when server side know opposite person not get message so we have to pass push notification him/her ...while opposite user offline?
  • DivineDesert
    DivineDesert over 9 years
    @DhavalBhadania You will need to call a webservice where you will send push notification. If you are using Robbihenson code, you will get it from XMPP isOnline function. If is checking if primary resource is available, it means user is online.
  • Dhaval Bhadania
    Dhaval Bhadania over 9 years
    @DivineDesert if (![user isOnline]) can we get opposite person status also? if it's not in my roasterlist.
  • DivineDesert
    DivineDesert over 9 years
    No, other person need to be in your roster list
  • DivineDesert
    DivineDesert over 9 years
    If you dont want to add users to roster, add them in one xmpp group
  • Dhaval Bhadania
    Dhaval Bhadania over 9 years
    @DivineDesert ohk, no i will adding in roaster list . after what i have to do ? can get status from [oppsiteuser isOnline]) ?
  • DivineDesert
    DivineDesert over 9 years
    Yes @DhavalBhadania, Once you add user in roster list, it will come, you will need to subscribe one user to other user's presence.
  • Dhaval Bhadania
    Dhaval Bhadania over 9 years
    hey@DivineDesert added in roaster list but don't know how to check opposite user online status? can you tell code or suggestion of it ?
  • Dhaval Bhadania
    Dhaval Bhadania over 9 years
    but not getting oppsite person active or inactive state there ? can you give code for it ? and how can i do test it explain more ,its pleasure for me .@DivineDesert thanks for rply .this issue try all way but didn't work yet.