This question is as simple as its title says: I'm trying to update a user nickname on his VCard but I cannot. I'm using this code:
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
dispatch_async(queue, ^{
XMPPvCardTemp *myVcardTemp = [[[self appDelegate] xmppvCardTempModule] myvCardTemp];
[myVcardTemp setNickname:#"a_nickname"];
[[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp:myVcardTemp];
});
I cannot imagine why this piece of code don't want to work while the same piece, but updating photo, is working like a charm:
NSData *imageData = UIImagePNGRepresentation(anImage);
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
dispatch_async(queue, ^{
XMPPvCardTemp *myVcardTemp = [[[self appDelegate] xmppvCardTempModule] myvCardTemp];
[myVcardTemp setPhoto:imageData];
[[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp:myVcardTemp];
});
Any help would be appreciated... this is driving me crazy
NOTES: I'm using OpenFire as XMPP server
And this is the stanza the server returns me when I'm trying to update the nickname
RECV: <iq xmlns="jabber:client" type="result" from="7db55e68-cb18-4826-befd-0eb9269637aa#000.000.000.000" to="7db55e68-cb18-4826-befd-0eb9269637aa#000.000.000.000/2cfc4f88"><chat_jorges xmlns="vcard-temp"><NICKNAME>chat_jorges</NICKNAME></chat_jorges></iq>
(I changed my server's ip for 000.000.000.000)
EDIT : I WAS TOTALLY WRONG DON'T READ THIS
Actually when I read the source code of XMPP, I wonder how it could set a value.
In XMPPvCardTempBase.h :
#define XMPP_VCARD_SET_STRING_CHILD(Value, Name) NSXMLElement *elem = [self elementForName:(Name)];
//it looks like a get and not a set??
And in XMPPvCardTemp.m :
- (void)setNickname:(NSString *)nick {
XMPP_VCARD_SET_STRING_CHILD(nick, #"NICKNAME");
}
Maybe there is something as KVC somewhere...
Can you try this in the source code:
- (void)setNickname:(NSString *)nick {
XMPP_VCARD_SET_STRING_CHILD(nick, #"NICKNAME") = nick ;
}
Related
Trying to create a very simple proof of concept iOS xmpp app with the robbiehanson xmpp frame work, just need to be able to send and receive messages and roster data. I can authenticate and send messages successfully, but when users attempt to respond to my messages I do not receive them. I have implemented the didReceiveMessage delegate method as follows:
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSLog(#"incoming message: %#", message);
}
but I never receive this log. If I log in with the existing web app or android app that communicates with this xmpp server I receive these messages, so I'm inclined to believe they are formatted properly. Is there a module I need to add to the XMPPStream for receiving messages? I'm setting up the stream like this (some of the string values have been changed for security and what not):
stream = [[XMPPStream alloc] init];
stream.enableBackgroundingOnSocket = YES;
stream.hostName = #"hostname.com";
stream.hostPort = 5222;
XMPPRosterCoreDataStorage* xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] initWithInMemoryStore];
XMPPRoster* xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
[stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
XMPPJID* jid = [XMPPJID jidWithUser:#"username" domain:#"domain.com" resource:#"iOS"];
[stream setMyJID:jid];
[xmppRoster activate:stream];
[stream connectWithTimeout:XMPPStreamTimeoutNone error:&error]
and then in the xmppStreamDidConnect method I do this to authenticate
NSString *myPassword = #"password";
NSError *error = nil;
[stream authenticateWithPassword:myPassword error:&error]
When I am sending a message out I use this snippet:
MPPJID* recipient = [XMPPJID jidWithString:#"user#domain.com"];
XMPPMessage* message = [[XMPPMessage alloc] initWithType:#"chat" to:recipient];
[message addBody:#"hello world"];
[stream sendElement: message];
I'm thinking there is something simple I am missing that someone who has used this before will be able to point out to me right away. I'm ready to supply other info if necessary for solving this issue.
I simply needed to broadcast my presence, then I was able to receive messages.
I added these lines to the streamDidAuthenticate method
XMPPPresence *presence = [XMPPPresence presence];
[sender sendElement:presence];
I have gone through the XEP 0184 and have done following implementation.
If XMPP is connected and packet then is send then i set the status for each message as SENT (✔︎) if I don't get following callback.
-(void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
If i get the received status from XEP 0184 implemented in Objective C, I set the status as Delivered (✔︎✔︎)
RECV: < message xmlns="jabber:client" from="+122232322#wer.com/2323"
to="+3343232322#wer.com/2223" lang="" >< received
xmlns="urn:xmpp:receipts" id="avv-33343"/ >< /message >
But my question is how to show the SEEN status for each message as readh XMPP 0079 that is Advanced Messaging protocol is doing this. But I could not find in Objective C.
Can anyone please help? If my direction is correct and I am missing something could you let me know?
A code snippet guidance would be much appreciated.
Here is my implementation.
Using the stack documentation help I have added the following lines to get the delivery receipts.
XMPPMessageDeliveryReceipts* xmppMessageDeliveryReceipts = [[XMPPMessageDeliveryReceipts alloc] initWithDispatchQueue:dispatch_get_main_queue()];
xmppMessageDeliveryReceipts.autoSendMessageDeliveryReceipts = YES;
xmppMessageDeliveryReceipts.autoSendMessageDeliveryRequests = YES;
[xmppMessageDeliveryReceipts activate:self.xmppStream];
Now due to this I get the following response for the send and RECV xml.
SEND: 111111111 for avv-33343 Id message.
RECV: < message xmlns="jabber:client" from="+122232322#wer.com/2323"
to="+3343232322#wer.com/2223" lang="" >< received
xmlns="urn:xmpp:receipts" id="avv-33343"/ >< /message >
But this is just giving me info that the message is delivered but how to send the SEEN receipts like above to intimate the sender that the other end user have acknowledged + SEEN the message.
Something like this ... RECV: < seen xmlns="urn:xmpp:receipts" id="222-4444"/ >
For seen status use same functionality as send a normal message with same id which message received and you want to mark seen on Sender device,
When on sender device receive a static message #"to#fromSeen" with same message id for sent/delivered message, When receiver get exist msg id already in db then your purpose resolve .
Code for send seen status
NSString *bodymessageString = [NSString stringWithFormat:#"to#fromSeen"];
NSString *str_loginUser = [NSString stringWithFormat:#"%##%#", [[NSUserDefaults standardUserDefaults]valueForKey:#"mobile"],kXMPPServer ];
NSString *str_OtherUser = [NSString stringWithFormat:#"%##%#",str_OtherUserRegName,kXMPPServer];
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:bodymessageString];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"from" stringValue:str_loginUser];
// [[[delegate xmppStream] myJID] bare]
[message addAttributeWithName:#"to" stringValue:str_OtherUser];
// NSString *messageID= [XMPPStream generateUUID];
[message addAttributeWithName:#"id" stringValue:str_msgID];
// NSXMLElement *request = [NSXMLElement elementWithName:#"request" xmlns:#"urn:xmpp:receipts"];
// [message addChild:request];
[message addChild:body];
[[delegate xmppStream] sendElement:message];
[ChatData GetUpdateToDatabase:str_msgID :#"Seen"];
Code for check message status in appdelegate file
if ([message isChatMessageWithBody])
{
if ([msg isEqualToString:#"to#fromSeen"])
{
BOOL is_Exist;
is_Exist = [ChatData GetAllReadyAvailable :message.elementID];
if (is_Exist == YES)
{
NSString *str_status = [ChatData getstatusChatBy:message.elementID];
if (![str_status isEqualToString:#"Seen"])
{
[ChatData GetUpdateToDatabase:message.elementID :#"Seen"];
}
}
}
else
{
BOOL is_Exist;
is_Exist = [ChatData GetAllReadyAvailable :message.elementID];
if (is_Exist == NO)
{
// Store message in DB
}
}
}
else if ([message hasReceiptResponse])
{
}
else if([message isErrorMessage])
{}
For changing my logged status I used the following code:
XMPPPresence *presence = [XMPPPresence presenceWithType:#"away"];
[[self xmppStream] sendElement:presence];
But I am not getting the reference of [self xmppStream]. So I changed to the following code:
XMPPPresence *presence = [XMPPPresence presence];
NSXMLElement *status = [NSXMLElement elementWithName:#"status"];
[status setStringValue:#"away"];
[presence addChild:status];
NSError *error = nil;
xmppStream = [[XMPPStream alloc] init];
[xmppStream disconnect];
NSString *myJID = [NSString stringWithFormat:#"%#", appDelegate.jid];
XMPPJID *JID;
JID = [XMPPJID jidWithString:myJID];
NSLog(#"%#",JID);
[xmppStream setMyJID:JID];
xmppStream.hostName=#"talk.google.com";
[xmppStream connect:&error];
[xmppStream sendElement:presence];
Still not getting the changed status. Please share your ideas. Thanks in advance.
You can change your status immediately after you're logged in via goOnline method as it is called after xmppStreamDidAuthenticate.
- (void)goOnline
{
// Initialize XMPPPresence variable
XMPPPresence *presence = [XMPPPresence presence];
// Initialize XML element <show/> for specifying your status
NSXMLElement *show = [NSXMLElement elementWithName:#"show"];
// Initialize XML element <status/> for describing your status
NSXMLElement *status = [NSXMLElement elementWithName:#"status"];
// If you want your user status to be shown as "Available"
[show setStringValue:#"chat"];
[status setStringValue:#"Available"];
// If you want your user status to be shown as "Busy"
[show setStringValue:#"dnd"];
[status setStringValue:#"Busy"];
// If you want your user status to be shown as "Away"
[show setStringValue:#"away"];
[status setStringValue:#"Away"];
// If you want your user status to be shown as "Off-day"
[show setStringValue:#"xa"];
[status setStringValue:#"Off-day"];
// Add the XML elements to XMPPPresence
[presence addChild:show];
[presence addChild:status];
// Update new presence to server
[xmppStream sendElement:presence];
}
For more information and an explanation to my code above, visit Change XMPPPresence to Away/Busy/Invisible.
You have to wait until after you're connected to send stanzas, by listening for xmppStreamDidAuthenticate on the delegate.
Also, don't bother to set the to or from JID when broadcasting your presence.
I am developing an application in that I want to update my avatar image. I am following XEP-0153 guidelines to update my avatar image and I constructed an NSXMLElement correspond to the following code in XEP-0153 and sent that element through XMPPStream.
<iq from='juliet#capulet.com'
type='set'
id='vc1'>
<vCard xmlns='vcard-temp'>
<PHOTO>
<TYPE>image/jpeg</TYPE>
<BINVAL>
Base64-encoded-avatar-file-here!
</BINVAL>
</PHOTO>
</vCard>
</iq>
The server responses the following error:
<iq xmlns="jabber:client" type="error" id="vc1" to="vvreddy50#gmail.com/83557F96">
<vCard xmlns="vcard-temp">
<photo>
<type>image/jpeg</type>
<binval>Base64-encoded-avatar-file-here</binval>
</photo>
</vCard>
<error code="500" type="wait">
<internal-server-error xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
</internal-server-error>
</error>
</iq>
Instead of <iq to='juliet#capulet.com' type='result' id='vc1'/>
Please can anyone post the code or the link related to update avatar image? Thanks in advance.
- (void)updateAvatar:(UIImage *)avatar
{
NSData *imageData = UIImagePNGRepresentation(avatar);
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
dispatch_async(queue, ^{
XMPPvCardTempModule *vCardTempModule = [[XMPPHandler sharedInstance] xmppvCardTempModule];
XMPPvCardTemp *myVcardTemp = [vCardTempModule myvCardTemp];
[myVcardTemp setName:[NSString stringWithFormat:#"%#",name.text]];
[myVcardTemp setPhoto:imageData];
[vCardTempModule updateMyvCardTemp:myVcardTemp];
});
}
#import "XMPPvCardTemp.h"
- (void)updateAvatar:(UIImage *)avatar{
NSData *imageData1 = UIImageJPEGRepresentation(avatar,0.5);
NSXMLElement *vCardXML = [NSXMLElement elementWithName:#"vCard" xmlns:#"vcard-temp"];
NSXMLElement *photoXML = [NSXMLElement elementWithName:#"PHOTO"];
NSXMLElement *typeXML = [NSXMLElement elementWithName:#"TYPE"stringValue:#"image/jpeg"];
NSXMLElement *binvalXML = [NSXMLElement elementWithName:#"BINVAL" stringValue:[imageData1 base64Encoding]];
[photoXML addChild:typeXML];
[photoXML addChild:binvalXML];
[vCardXML addChild:photoXML];
XMPPvCardTemp *myvCardTemp = [[[self appDelegate] xmppvCardTempModule]myvCardTemp];
if (myvCardTemp) {
[myvCardTemp setPhoto:imageData1];
[[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp
:myvCardTemp];
}
else{
XMPPvCardTemp *newvCardTemp = [XMPPvCardTemp vCardTempFromElement:vCardXML];
[[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp:newvCardTemp];
}
}
From the XMPP Core RFC, <error type='wait'> means:
retry after waiting (the error is temporary)
so your code should wait a while and re-send the request.
(This is assuming that you are actually sending a base64-encoded JPEG image as the BINVAL of your vCard. The reply from the server doesn't correspond to the request you say you sent, so I'm assuming you've edited both. It would be better to include the exact request and reply in your question, but truncate the base64-encoded image to a few characters for concision.)
I'm trying to set the users presence to away (or anything at the moment). I'm using the following code but it doesn't seem to do anything.
XMPPPresence *presence = [XMPPPresence presence];
NSXMLElement *show = [NSXMLElement elementWithName:#"show" stringValue:#"away"];
NSXMLElement *status = [NSXMLElement elementWithName:#"status" stringValue:#"away"];
[presence addChild:show];
[presence addChild:status];
[[self xmppStream] sendElement:presence];
I've used iChat to make sure all the presence subscriptions on my Ejabberd server are correct and working. This is driving me crazy, am I missing something?
I figured it out, turns out the presence wasn't being sent out by the app as I'd missed this out:
- (MMApplication *)appDelegate {
return (MMApplication *)[[UIApplication sharedApplication] delegate];
}
- (XMPPStream *)xmppStream {
return [[self appDelegate] xmppStream];
}
Works perfectly now