Getting duplicate message while retrieving messages from History - ios

I'm created group chat in Openfire & XMPP.
I'm getting history from Openfire server using "since" while joining room.
Here is my code :
XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc] init];
XMPPJID *roomJID = [XMPPJID jidWithString:chatWithUser];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:self.xmppStream];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#"since" stringValue:finalDate];
[xmppRoom joinRoomUsingNickname:self.xmppStream.myJID.user
history:history
password:nil];
I store message in local so next time user when login it fetch last message date from local and send it to server to fetch all message after that date.
finalDate is date from that i fetch from local and send it to server.
But what happern is that when i send finalDate to server it fetch last message also that i already stored in local database.
If my last message from localDB is 'Hi' and date '2016-08-08T04:52:42.347Z' than it fetch 'Hi' from server.
Why this happen ? I want message from server after date.

The problem of XMPP MUC specification is - history messages are stamped with server time, while you ask since your local time. There is an XMPPAutoTime module in XMPPFramework, which trying to track time difference and you should add that difference for any timestamp-based queries. Check the detailed description here

Related

How to retrieve offline message openfire XMPP?

I Successfully implemented group chat using Openfire with XMPP.
Now when User A send message to User B who is offline, So when User B is online how can I retrieve all unread/offline messages from server.
I'm doing this stuff to join the room but it getting all messages from server :
- (void) getJoinRoom
{
XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc] init];
XMPPJID *roomJID = [XMPPJID jidWithString:chatWithUser];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:self.xmppStream];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:self.xmppStream.myJID.user
history:nil
password:nil];
}
How do I fetch those offline messages ?
As per XMPP standard, only one-one chat messages are eligible for offline storage, so messages of type="groupchat" are never stored in offline storage in XMPP Servers.
As per MUC XEP if a user goes offline, it doesn't count as a participant of the room any more. So when the user comes online, he will have to join the room by sending presence packet to the room.

Xmpp MultiUserChat (MUC) Group Does not remain stable

I created an Xmpp Chat App where I have implemented the one-to-one and group chat.
The Chat itself is working fine.
The issue is in Group chat. I created a group with 2-3 members, again the chat is working fine, but when I kill the application and restart it, I'm not getting the group messsages from any of the groups I have created.
while I am connected to the XMPP Server and re-join any group then I get the messages.
My problem is that I have to join into groups again every time after I kill the app completly.
Please let me know How I can get the messages or join automatically in group when i open the application from killed state.
You need to send presence to XMPP server once your application launched or come out from background. so the XMPP server understand that respective group is ready to handle event.
Edit : you can send presence using following code.
- (void)goOnline {
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
NSXMLElement *show = [NSXMLElement elementWithName:#"show"
stringValue:#"dnd"];
NSXMLElement *status = [NSXMLElement elementWithName:#"status" stringValue:#"available"];
NSXMLElement *priority = [NSXMLElement elementWithName:#"priority" stringValue:#"24"];
[presence addChild:show];
[presence addChild:status];
[presence addChild:priority];
[_xmppStream sendElement:presence];
[self createOrJoinRoom];
}
- (void)createOrJoinRoom {
if ([appDelegate.xmppStream isConnected]) {
NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:#"XMPPUserId"];
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
[presence addAttributeWithName:#"from" stringValue:[[appDelegate.xmppStream myJID]full]];
[presence addAttributeWithName:#"to" stringValue:[NSString stringWithFormat:#"%##%#/%#", #"newone", GroupChatRoomName,myJID]];
NSXMLElement *xelement = [NSXMLElement elementWithName:#"x" xmlns:XMPPMUCNamespace];
[presence addChild:xelement];
[appDelegate.xmppStream sendElement:presence];
}
}
May this help you.
You have to join all your previous join/connected groups. Because in iOS if you kill your app then you left from your created or joined groups.
So every time in this section of the code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
you have to join your group again.
Below is demo code for it :
XMPPRoomHybridStorage *xmppRoomStorage1 = [XMPPRoomHybridStorage sharedInstance];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomStorage1 jid:RoomName];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:appDelegate.Obj_xmppManager.xmppStream];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#"maxstanzas" stringValue:#"1"];
[xmppRoom joinRoomUsingNickname:self.xmppStream.myJID.user history:nil];
Adding to the Presence answer, I would also check more basic things -
Are the rooms (group chat) you create persistant?
or do you have to create the room again every time you connect?
(notice the difference between 'openning' and 'creating').
On some servers, rooms are temporary by default - you can check this by connecting with 2 seperate clients, send some messages, disconnect only one of them, and reconnect - if you do see the messages that were sent in your reconnected client - this might be your issue, can you show the parameters you pass to the server when you create the room?.
Is the server you are using configured to send history messages by default, and if so how many, again, server implementations may vary, could you share some information on the server you are using (openfire, ejabbered, prosody)? or a snippet from you configuration file?
Is it possible you are getting the messages, but not showing them correctly, maybe not refreshing the screen\view when first entering a room? any log messages?
I am also facing this issue since a week and looking for solution and after a lot of search on google and stack overflow i got a clue which solve this issue.
In my case group created successfully and chat is working good with members and members can send me chat too but when any member of group logout or kill the app and then login again he is unable to send message is this group and group says in response Only occupants are allowed to send messages to the conference.
In my case when user tap on group to go into group and start chat i call this method to join group.
NSString *roomJID = [NSString stringWithFormat:#"%##conference.yourHostName", roomJid];
XMPPJID *jid = [XMPPJID jidWithString:roomJID];
_xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomCoreDataStorage jid:jid dispatchQueue:dispatch_get_main_queue()];
[_xmppRoom activate:stream];
[_xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppRoom joinRoomUsingNickname:stream.myJID.bare history:nil];
Hope this will work for you too
By default a MUCRoom will send some history to newly joined user, the number is determined by config, under mod_muc: history_size:.
Or you need to explicitly request for some amount of history while sending the Presence, doc:
<presence
from='hag66#shakespeare.lit/pda'
id='n13mt3l'
to='coven#chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxstanzas='20'/>
</x>
</presence>

How to create a new group for chat using xmppframework?

Hi I'm developing a chat application in IOS and completed one to one chat, after searching a lot about groupChat, unable to got how to create a normal group in xmppframework.
What I already tried here is a link
iOS XMPP group chat implementation
Accepting chatroom invitation
How to create MultiUserChatRoom using XMPPFramework in iPhone
XMPPFramework - How to Create a MultiUserChat Rooms?
But didnt get any positive response from these above links,
In coding I tried
XMPPRoomCoreDataStorage *rosterstorage = [[XMPPRoomCoreDataStorage alloc] init];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:rosterstorage jid:[XMPPJID jidWithString:#"test#conference.domainName.com/rohit"] dispatchQueue:dispatch_get_main_queue()];
[xmppRoom configureRoomUsingOptions:nil];
[xmppRoom activate:[self xmppStream]];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
[xmppRoom inviteUser:[XMPPJID jidWithString:#"abc#domainName.com"] withMessage:#"Hi join room"];
Also this
- (void)createOrEnterRoom:(NSString *)roomName
{
//here we enter a room, or if the room does not yet exist, this method creates it
//per XMPP documentation: "If the room does not yet exist, the service SHOULD create the room"
//this method accepts an argument which is what you would baptize the room you wish created
XMPPPresence *presence = [XMPPPresence presence];
NSString *room = [roomName stringByAppendingString:#"#conference.domain.com"];
[presence addAttributeWithName:#"to" stringValue:room];
NSXMLElement *x = [NSXMLElement elementWithName:#"x" xmlns:#"http://jabber.org/protocol/muc"];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#"maxstanzas" stringValue:#"50"];
[x addChild:history];
[presence addChild:x];
[[self xmppStream] sendElement:presence];
}
Last one is
-(void)createGroup
{
#try {
NSString *username=#"user_3";//[self.userDefault valueForKey:#"userid"];
NSXMLElement *presenceElement=[NSXMLElement elementWithName:#"presence"];
[presenceElement addAttributeWithName:#"type" stringValue:#"groupchat"];
[presenceElement addAttributeWithName:#"from" stringValue:[NSString stringWithFormat:#"%#%#",username,HostName]];
[presenceElement addAttributeWithName:#"to" stringValue:[NSString stringWithFormat:#"testGroup#conference.%#/%#",HostName,username]];
NSXMLElement *xElement=[NSXMLElement elementWithName:#"x" xmlns:#"http://jabber.org/protocol/muc"];
NSXMLElement *historyElement=[NSXMLElement elementWithName:#"history"];
[xElement addChild:historyElement];
[presenceElement addChild:xElement];
[self.xmppStream sendElement:presenceElement];
}
#catch (NSException *exception) {
}
}
Anyone please show me a way to solve out this. Please also let me know if we need to configure something extra in ejjabered configuration.
Please find go through this i found best and detailed answer here .
Trouble creating xmpp muc room: Code 503 (service unavailable)
Infact group chat is not provided by XMPP, its a chat room that you have created with XMPPRoom,
or you can say conversation.
You cant send offline group messages with this.
I have implement Group chat in my http://www.catchbuddies.com/ project with the help of other custom server.
You can make and configue group chat with the help of some webservces for Groups.
You should check your muc settings of ejabberd server configuration.
make sure muc host is set correctly.
in my case, I changed host to {host, "pub.#HOST#"}, then I tried to join room "test#conference.#HOST#" always got service unavailable error, it took me a whole night to fix.
also, you can use imessage login to your jabber server with admin user, and create chat room before you run ios client.
Change ejabberd log level to debug may help a lot.
For group creation change setting for muc_room. Also prefer this url will suggest the way for setting https://serverfault.com/questions/185770/configuring-ejabberd-for-multi-user-chat

Single chat and group chat at same time in xmpp

In my application my User to User single chat is working perfectly.
but if I send the invitation of Room to any User then single chat is not working.
and I didn't attach group chat code in app yet. just send invitation of Room to other user and then creating single chat.
is there anything logically I missed ?
My code for creating and inviting
XMPPRoomMemoryStorage * _roomMemory = [[XMPPRoomMemoryStorage alloc]init];
NSString* roomID = [NSString stringWithFormat:#"%##conference.room",strGlobalRoomNameForLogin];
XMPPJID * roomJID = [XMPPJID jidWithString:roomID];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:_roomMemory jid:roomJID dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom joinRoomUsingNickname:[NSString stringWithFormat:#"%#",strCureentUserName] history:nil];
//NSLog(#"strCureentUserName %#",strCureentUserName);
//.........inviting the Friend.......
for (int i=0; i<[arrUserName count];i++) {
NSString *strInviteUserEmalid = [[arrUserName objectAtIndex:i] stringByReplacingOccurrencesOfString:#"#" withString:#"$"];
// NSLog(#"strInviteUserEmalid %#",strInviteUserEmalid);
[xmppRoom inviteUser:[XMPPJID jidWithString:[NSString stringWithFormat:#"%##user",strInviteUserEmalid]] withMessage:#"Come Join me in this room"];
}
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
[xmppRoom addDelegate:_roomMemory delegateQueue:dispatch_get_main_queue()];
For large numbers of invitees, you may be running into "karma" limits on your server. Try sending the invites slower by adding a timeout.

Saving XMPP Multi User chat messages through XMPP MessageArchiving in iOS

I am developing a chat application in iOS using XMPP. I have so far successfully implemented and tested a single user chat scenario, i.e. sending, receiving, saving and retrieving messages.
The problem now em facing is that now when handling Multi User Chat scenarios em receiving it but not able to save them using XMPP MessageArchiving hence cant retrieve them either.
Anyone who has gone through this process/problem?
Thank you in advance
Messages with groupchat type may be saved within XMPPRoom.xcdatamodel, you need to initialize the XMPPRoomCoreDataStorage in your xmpp setup like:
XMPPRoomCoreDataStorage *xmppRoomStorage = [[XMPPRoomCoreDataStorage alloc] init];
So, this class implements a method to insert all the messages ROOM within the correct data model (in our case, all the outgoing and incoming messages are saved in XMPPRoom.xcdatamodel).
- (void)insertMessage:(XMPPMessage *)message
outgoing:(BOOL)isOutgoing
forRoom:(XMPPRoom *)room
stream:(XMPPStream *)xmppStream
More XEP-0045 info http://xmpp.org/extensions/xep-0045.html
You can use this code for a saving room messages
NSString *xmppRoomJIDString = [NSString stringWithFormat:#"%##conference.your_host", #"your_room_name"];
XMPPJID *roomJID = [XMPPJID jidWithString:xmppRoomJIDString];
XMPPRoomCoreDataStorage *roomCoreDataStorage = [XMPPRoomCoreDataStorage sharedInstance];
XMPPRoom *xmppRoom = [[XMPPRoom alloc]
initWithRoomStorage:roomCoreDataStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:#"your_nicke_name" history:nil];
[xmppRoom fetchConfigurationForm];

Resources