I have created new room for group chat by using this-
XMPPRoomCoreDataStorage *rosterstorage = [[XMPPRoomCoreDataStorage alloc] init];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:rosterstorage jid:[XMPPJID jidWithString:#"viratsroom#conference.praveens-mac-mini.local"] dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:[[self appDelegate] xmppStream]];
if ([xmppRoom preJoinWithNickname:#"viratsRoom"]) {
NSLog(#"room created");
[xmppRoom joinRoomUsingNickname:#"viratsroom11" history:nil];
}
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
[xmppRoom addDelegate:[self appDelegate] delegateQueue:dispatch_get_main_queue()];
Room is getting created but with error
I have traced at server side and found this error-
"presence xmlns="jabber:client" from="viratsroom#conference.iisd09/arup" to="arup#iisd09/ClientXMPP" type="error" error code="404" type="wait" recipient-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"
Room wasnt configured properly hence all errors
calling this immediately after creating room doesnt work-
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
it takes a little time to create room after that u can configure the room.
[self performSelector:#selector(ConfigureNewRoom:) withObject:nil afterDelay:2];
Thanks
Related
XMPP push notifications causing problems (delay + duplications) in messages.
I have successfully created a chat application using XMPP + Ejabberd.
Without Push Notifications:
Both single and group chat messages are working perfectly.
With Push Notifications:
Sometimes everything works perfectly.Notifications are triggered and messages are received with out any delay or duplications.
Sometimes no notifications are triggered (while app in background) but messages are received perfectly.
Sometimes notifications are triggered but messages are received with delay and duplications.
Everything on the sever side is configured correctly.They advised to fix your issues by making sure each session connects with one persistent resource, making connection stable using whitespace keep alive and when connection is lost just rebinding with same resource.
I have stream management,xmppStream.enableBackgroundingOnSocket and App provides Voice over IP services background mode enabled.
When user logs out or app is terminated i teardown the stream and send an unavailable presence.
Below is my code for xmpp stream push notifications and connect/disconnect.
I am pulling out my hair over this.if you guys have any idea please let me know.
Thanks.
#pragma mark - Connect/Disconnect
- (BOOL)connect {
if (!_xmppStream) {
NSLog(#"Setting up Stream");
[self setupStream];
}
if (![_xmppStream isDisconnected]) {
return YES;
}
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:#"userID"];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"userPassword"];
if (jabberID == nil || myPassword == nil) {
return NO;
}
[_xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
_password = myPassword;
NSError *error = nil;
if (![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Can't connect to server! %#", [error localizedDescription]] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
return NO;
}
return YES;
}
- (void)disconnect {
[self goOffline];
[self teardownStream];
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
[self goOnline];
//Stream Management
NSXMLElement *enable = [NSXMLElement elementWithName:#"enable" xmlns:#"urn:xmpp:sm:3"];
[enable addAttributeWithName:#"resume" stringValue:#"true"];
[_xsm.xmppStream sendElement:enable];
//Push
[self configurePushNotifications];
//
}
-(void)configurePushNotifications{
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:#"userID"];
NSXMLElement *iq = [NSXMLElement elementWithName:#"iq"];
[iq addAttributeWithName:#"type" stringValue:#"set"];
[iq addAttributeWithName:#"id" stringValue:idString];
NSXMLElement *push = [NSXMLElement elementWithName:#"push" xmlns:#"p1:push"];
NSXMLElement *keepalive = [NSXMLElement elementWithName:#"keepalive"];
[keepalive addAttributeWithName:#"max" integerValue:30];
NSXMLElement *session = [NSXMLElement elementWithName:#"session"];
[session addAttributeWithName:#"duration" integerValue:60];
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body addAttributeWithName:#"send" stringValue:#"all"];
[body addAttributeWithName:#"groupchat" stringValue:#"true"];
[body addAttributeWithName:#"from" stringValue:jabberID];
NSXMLElement *status = [NSXMLElement elementWithName:#"status"];
[status addAttributeWithName:#"type" stringValue:[NSString stringWithFormat:#"New message from %#",jabberID]];
NSXMLElement *offline = [NSXMLElement elementWithName:#"offline" stringValue:#"true"];
[push addChild:keepalive];
[push addChild:session];
[push addChild:body];
[push addChild:status];
[push addChild:offline];
NSXMLElement *notification = [NSXMLElement elementWithName:#"notification"];
[notification addChild:[NSXMLElement elementWithName:#"type" stringValue:#"applepush"]];
[notification addChild:[NSXMLElement elementWithName:#"id" stringValue:_userDeviceToken]];
[push addChild:notification];
NSXMLElement *appid = [NSXMLElement elementWithName:#"appid" stringValue:#"appid"];
[push addChild:appid];
[iq addChild:push];
[[self xmppStream] sendElement:iq];
}
- (void)setupStream {
_xmppStream = [[XMPPStream alloc] init];
_xmppStream.hostName = kHostName;
_xmppStream.hostPort = kHostPort;
_xmppStream.enableBackgroundingOnSocket = YES;
[_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
//XMPPReconnect
_xmppReconnect = [[XMPPReconnect alloc] init];
[_xmppReconnect activate:_xmppStream];
//Stream Management
_xsm = [[XMPPStreamManagement alloc] init];
[_xsm enableStreamManagementWithResumption:YES maxTimeout:0];
[_xsm activate:_xmppStream];
//Last Activity
_xmppLastActivity = [[XMPPLastActivity alloc] initWithDispatchQueue:dispatch_get_main_queue()];
[_xmppLastActivity addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppLastActivity activate:_xmppStream];
}
- (void)goOnline {
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
}
- (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:#"unavailable"];
[[self xmppStream] sendElement:presence];
}
- (void)teardownStream {
[_xmppStream disconnect];
[_xmppStream removeDelegate:self];
[_xmppReconnect removeDelegate:self];
[_xmppLastActivity removeDelegate:self];
[_xmppReconnect deactivate];
_xmppStream = nil;
_xmppReconnect = nil;
_xmppLastActivity = nil;
}
You need to make sure that you are passing the resource when you connect to ejabberd. The resource should be randomly generated on first app install and on subsequent login, you should always use the same resource. Otherwise you are created a new long running detached session on each new login on the server and causing messages to be routed to all pending sessions. When those expires they are routed again etc.
In XMPP, the resource is the identifier of the device basically. You need to generate the JID for login with a string of form "user#domain/resource"
you should notify stream management to disconnect your session and
call this method for disconnect in tearDown :
[self.stream disconnectAfterSending];
I am developing an IOS Chat application using XMPP Protocol(ejabberd). My chat room is created at my server, it return roomID to me.
I am facing an issue in room/group chat. When i am sending a single message it is repeating more than once like 3 to 4 times.How to fix this. My code is here
XMPPJID *roomJID = [XMPPJID jidWithString:[roomDict objectForKey:KEY_group_id]];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomCoreDataStorage jid:roomJID dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:[ChatHandler sharedInstance].xmppStream];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
[self insertRoomObjectWithDictionary:roomDict];
[xmppRoom joinRoomUsingNickname:[[ChatHandler sharedInstance] xmppStream].myJID.user
history:nil
password:#""];
[xmppRoom fetchConfigurationForm];
return xmppRoom;
Following code snippet worked for me.. Try it for your code...
I have sent uuid of my device as child while sending message and checked the same uuid at the time of incoming message :
-(void)sendMessageWithBody:(NSString *)messageBody
{
if ([messageBody length] == 0) return;
NSXMLElement *body = [NSXMLElement elementWithName:#"body" stringValue:messageBody];
XMPPMessage *message = [XMPPMessage message];
[message addChild:body];
NSString *uuidString=[UIDevice currentDevice].identifierForVendor.UUIDString;
NSXMLElement *myMsgLogic=[NSXMLElement elementWithName:#"myMsgLogic" stringValue:uuidString];
[message addChild:myMsgLogic];
[self sendMessage:message];
}
-(void)xmppRoom:(XMPPRoom *)sender didReceiveMessage:(XMPPMessage *)message fromOccupant:(XMPPJID *)occupantJID;
{
[self handleIncomingMessage:message room:xmppRoom];
}
-(void)handleIncomingMessage:(XMPPMessage *)message room:(XMPPRoom *)room
{
NSString *uuidString=[UIDevice currentDevice].identifierForVendor.UUIDString;
NSString *messageLogic= [[message elementsForName:#"myMsgLogic"].firstObject stringValue];
if ([uuidString isEqualToString:messageLogic]) {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"handleIncomingMessage" message:[message body] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
}
I have the same chat application using xmpp ejabbered. I was also facing the same problem. In my case on xmpp server they have set offline message storage to 100. If in offline mode the message limit crossed 100 then from 101th message I will get bounce back that message. So as a solution we changed the offline message limit to 500.
{mod_offline_odbc, [
{user_max_messages, 500}
]}
I am developing Chat Application using XMPPFramwwork in iPhone.I successfully completed one to one chat,now i want to develop multiuser chat in my application.
I tried the fallowing code but any delegate methods of XMPPRoomDelegate are not called.how can i start to create chat room.When and how the roomdelegate methods get called....any reply thanks inadvance.
XMPPStream *xmppStream = [[XMPPStream alloc] init];
XMPPRoomCoreDataStorage *xmppRoomStorage = [XMPPRoomCoreDataStorage sharedInstance];
XMPPJID *roomJID = [XMPPJID jidWithString:#"vvreddy50#gmail.com"];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomStorage jid:roomJID dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
Two problems:
XMPPFramework is mostly asynchronous. That means you need to call -fetchConfigurationForm after you've authenticated, in your -xmppStreamDidAuthenticate: method.
If those two calls need to be made in sequence, then call -configureRoomUsingOptions in -xmppRoom:didFetchConfigurationForm:.
Nothing at all will happen unless you call -connect: on the stream. Make sure to implement -xmppStreamDidConnect: and initiate authentication with the server in that method.
I'm trying for group chat in iphone,am able to use single chat successfully.
I have created new room using following code successfully.
XMPPRoomCoreDataStorage *rosterstorage = [[XMPPRoomCoreDataStorage alloc] init];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:rosterstorage jid:[XMPPJID jidWithString:#"viratsroom#conference.praveens-mac-mini.local"] dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:[[self appDelegate] xmppStream]];
if ([xmppRoom preJoinWithNickname:#"viratsRoom"]) {
NSLog(#"room created");
[xmppRoom joinRoomUsingNickname:#"viratsroom11" history:nil];
}
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
[xmppRoom addDelegate:[self appDelegate] delegateQueue:dispatch_get_main_queue()];
now under users in this group there is one user shown on openfire server which is correct.
my questions are,
1)where and how to handle invitation message to join group?
2)I have tried to join the same group made above by using following code
XMPPRoomCoreDataStorage *rosterstorage = [[XMPPRoomCoreDataStorage alloc] init];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:rosterstorage jid:[XMPPJID jidWithString:#"viratsroom#conference.praveens-mac-mini.local"] dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:[[self appDelegate] xmppStream]];
[xmppRoom joinRoomUsingNickname:#"viratsroom11" history:nil];
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
[xmppRoom addDelegate:[self appDelegate] delegateQueue:dispatch_get_main_queue()];
the room name now is shown in my offline users list.
now users under this room on openfire server should increase to two as one more user has joined this room but it still shows only one previous user member.
Am I missing something? any mistake in code ? please help!
Thanks .
I got this,
Room wasnt configured properly hence all problems
calling this immediately after creating room doesnt work-
[xmppRoom fetchConfigurationForm];
[xmppRoom configureRoomUsingOptions:nil];
it takes a little time to create room after that u can configure the room.
[self performSelector:#selector(ConfigureNewRoom:) withObject:nil afterDelay:2];
:)
Im developing an app for iPhone, in wich one of the functionalities is an instant message system, using XMPPFramework. By now, im testing it with Google Talk. The delegate is the same class that manages the User Interface. So, I got this code:
In viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupStream];
}
The setupStream method:
- (void) setupStream
{
NSLog(#"Inside setupStream");
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[self connect];
}
The connect method:
- (BOOL) connect
{
NSLog(#"Inside connect method");
General *general = [General sharedManager];//this is a singleton to manage settings for every user
NSString *chatid;
NSString *chatpass;
//chatid=[general user];
chatid=#"somegmailaccount#gmail.com";
xmppStream.myJID=[XMPPJID jidWithString:chatid];
if (![xmppStream isDisconnected]) {
return YES;
}
NSError *error = nil;
if (![xmppStream connect:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
In xmppStreamDidConnect method:
- (void) xmppStreamDidConnect:(XMPPStream *)sender
{
[xmppStream authenticateWithPassword:#"password" error:NULL];
[self goOnline];
}
And goOnline method:
- (void) goOnline
{
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
NSLog(#"Presence sent");
}
With this, the presence is not sent. I have another google account that I try for testing (say, testing#gmail.com) and in this account the presence of somegmailaccount.gmail.com is not seen. Both accounts are connected and know each other, since I used this same accounts to develop the Android app.
Any idea about what i´m doing wrong? Any help is appreciated.
Thank you very much.
I found it! The presence is not sent this way:
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
Insted, i have done it this way:
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
[xmppStream sendElement:presence];
This way, the presence is sent without any problem :)
With this code, i implement method xmppStreamDidAuthenticate:(XMPPStream *)sender
and the program DO enter that method without any call from my code. But if i put
[xmppStream setHostName:#"talk.google.com"];
[xmppStream setHostPort:5222];
... in method connect, the program DO NOT enter that method, nor xmppStreamDidConnect.
Im getting mad.