I am starting to develop one XMPP ios client using robbiehanson/XMPPFramework I tried to achieve user is tying.. ie Typing indicator. It is working when both the users are using ios client. When I tried to use multiple client ie one user is using iOS client and another user using Spark desktop clien, the typing indicator is not working.
//Send Typing notification
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:self.userprofile.jidStr];
// [message addChild:body];
// chat notifications
XMPPMessage *xmppMessage = [XMPPMessage messageFromElement:message];
[xmppMessage addComposingChatState];
[appDelegate.xmppStream sendElement:xmppMessage];
// For Receive Typing Notification
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
if ([message hasComposingChatState]) {
self.statusLabel.text=#"is typing...";
}
}
The Typing notification is working fine when both users using my iOS client. But when one using ios client and another user using different client, the Typing notification is not working,
Please provide me the best way to achieve this.
Replace following line
[xmppMessage addComposingChatState];
with
[xmppMessage addMarkableChatMarker];
Other code is fine. Try this.
You need to implement xmpp-0022 , in this way messaging apps implements typing, sent, delivered and seen status
http://xmpp.org/extensions/xep-0022.html#sect-idp643808
I am looking for a way to retrieve the profile information of a LinkedIn user by making a post request, I have read these two LinkedIn pages but it doesn't seem to explain much, or I couldn't understand much of it:
REST API LinkedIn
basic profile informations
I have seen these example on stackoverflow but I didn't understood to much:
http://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,email-address,formatted-name,phonetic-last-name,location:(country:(code)),industry,distance,current-status,current-share,network,skills,phone-numbers,date-of-birth,main-address,positions:(title),educations:(school-name,field-of-study,start-date,end-date,degree,activities))
I am only interested to retrieve the skills section the one that on the website appears as so:
There's a fantastic library for LinkedIn-iOS integration by Kirsten Jones, you can use that to make calls to the LinkedIn API. You need an access token to make calls.
https://github.com/PrincessPolymath/LinkedIn-OAuth-Sample-Client
Make calls like this:
NSURL *url = [NSURL URLWithString:#"http://api.linkedin.com/v1/people/~:(id,first-name,last-name,maiden-name,formatted-name,phonetic-last-name,location:(country:(code)),industry,distance,current-status,current-share,network,skills,phone-numbers,date-of-birth,main-address,positions:(title),educations:(school-name,field-of-study,start-date,end-date,degree,activities))"]];
OAMutableURLRequest *request =
[[OAMutableURLRequest alloc] initWithURL:url
consumer:oAuthLoginView.consumer
token:oAuthLoginView.accessToken
callback:nil
signatureProvider:nil];
[request setValue:#"json" forHTTPHeaderField:#"x-li-format"];
OADataFetcher *fetcher = [[OADataFetcher alloc] init];
[fetcher fetchDataWithRequest:request
delegate:self
didFinishSelector:#selector(profileApiCallResult:didFinish:)
didFailSelector:#selector(profileApiCallResult:didFail:)];
- (void)profileApiCallResult:(OAServiceTicket *)ticket didFinish:(NSData *)data
{
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSDictionary *profile = [responseBody objectFromJSONString];
if ( profile )
{
name.text = [[NSString alloc] initWithFormat:#"%# %#",
[profile objectForKey:#"firstName"], [profile objectForKey:#"lastName"]];
headline.text = [profile objectForKey:#"headline"];
.....and get skills and other user details
}
}
Use tool:https://apigee.com/console/linkedin
API to get the list of Skills:
https://api.linkedin.com/v1/people/~:(id,num-connections,skills)?format=json
I tried it in the Console tool and able to fetch the skills for my profile. I think the individual skill ID with above request should help you to get further information. Try it out.
If anyone is reading this answer, the LinkedIn API has limited access as of May 2015. You will need to apply to their Apply with LinkedIn program to access full profile fields including skills.
https://developer.linkedin.com/docs/fields
I have fair amount of experience working with the linkedIn API. It's been a little while, but hopefully this will set you on the right track.
To get profile information from a linked in user who is one of your connections you need a format like follows:
NSString *theRequest = [NSString stringWithFormat:#"https://api.linkedin.com/v1/people/id=abc123:(first-name,last-name,picture-url,location:(name))?oauth2_access_token=%#&format=json", accessToken];
This request will return the first name, last name, profile picture url, and location of the user with the id specified.
You can see a list of field types you can request by checking out linkedIn's documentation on their profile field descriptions here:
https://developer.linkedin.com/docs/fields
If you're wondering how to get the id of the user whose profile information you want request in the first place, you can make request for some basic info (including ids) of all your connections like this:
NSString *basicConnectionInfo = [NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~/connections:(id,first-name,last-name)?oauth2_access_token=%#&format=json", accessToken];
This request will give you the id, first name, and last name of all of your connections. After you've gotten the id of the person you want, you can make a request using the user's id (as shown in the first example).
Now for the slightly unfortunately news... If you followed the link provided above, you'll notice that the skills field is part of the "Member profile fields available to Apply with LinkedIn developers". I'm assuming you'll have to follow this link they provided: https://developer.linkedin.com/docs/apply-with-linkedin in order to access the skills member profile field.
I have not applied with LinkedIn. So, I haven't tested a call to the skills field. But, I'm guessing it'll be similar to the examples I've shown you. Hope this helps!
In my application utilizing XMPPFramework, I have a login page to authenticate one user.
Once logged in, I wish to show the displayName of the user in my status page. The displayName is a NSString in XMPPUserCoreDataStorageObject.
The following line returns me the XMPPJID of my currently logged-in user. I thought this would be useful to check against my roster to get his displayName.
[[[self appDelegate] xmppStream] myJID];
However, placing the above in the code below returns me a null.
XMPPUserCoreDataStorageObject *user = [[[self appDelegate] xmppRosterStorage]
userForJID:[[[self appDelegate] xmppStream] myJID]
xmppStream:[[self appDelegate] xmppStream]
managedObjectContext:[[self appDelegate] managedObjectContext_roster]];
Appreciate any advice on how to go about retrieving the displayName of the current user.
As vitalyster mentioned in the comment above, there is no way to retrieve my own display name if I am logged in.
To verify that, I went to my Openfire server settings.
In Users/Groups > User Summary > KeithOYS > Roster, there is no same user called KeithOYS in the roster list.
Same concept applies for every other users.
In a nutshell, every user has all other users in their Roster (as long as they are classified under the same Group), all except himself.
I have got the user name of logged in user with following code.
XMPPJID *myjid = [[[self appDelegate]xmppStream]myJID];
NSString *userName = [NSString stringWithFormat:#"%#",myjid.user];
Hope it will help someone.
I am implementing XMPP in my ios app. I am aware of XMPPMessage+XEP_0085 category which has a few simple methods like addActiveChatState, addComposingChatState and a few others. I want to show chat notifications e.g. when user is typing a message or paused. I am using following code to send message:
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:user];
[message addAttributeWithName:#"id" stringValue:messageID];
[message addChild:body];
[message addChild:setting];
// chat notifications
XMPPMessage *xmppMessage = [XMPPMessage messageFromElement:message];
[xmppMessage addActiveChatState];
[xmppMessage addComposingChatState];
[xmppMessage addPausedChatState];
[xmppMessage addInactiveChatState];
[xmppMessage addGoneChatState];
[_appDelegate.xmppStream sendElement:xmppMessage];
In which xmpp delegate I should receive these notifications. I am not receiving chat notifications in
- (XMPPMessage *)xmppStream:(XMPPStream *)sender willReceiveMessage:(XMPPMessage *)message
delegate.
You are right, XMPPMessage+XEP_0085 category just define some simple methods to add chat state info, but also there are methods to check if chat state exists in message. So, you need to write an XMPPModule which will process message in -xmppStream:... didReceiveMessage: (note, you should use didReceiveMessage) and "multicast" events to others if message hasChatState and/or hasComposingChatState, etc. You can see examples of XMPPModule in the implementations of other XMPP extensions, e.g. XMPPPing
#vitalyster is correct to an extent. This is what I have followed to receive typing notifications properly:
After setting up your XMPPMessage, add chatMarkable to the message:
XMPPMessage *xmppMessage = [XMPPMessage messageFromElement:message];
[xmppMessage addMarkableChatMarker];
and then send new xmppMessage object.
When receiving notification, check if message contains hasInactiveChatState or hasComposingChatState and handle the UI part accordingly.
You guys might need to add some checks according to the project requirement and handling the typing notifications.
Problem : How can I get a successful TURN Connection using the iOS XMPPFramework and an OpenFire Server. I want to be able to send and recieve files.
Note : The base of my code is from the following tutorial : http://mobile.tutsplus.com/tutorials/iphone/building-a-jabber-client-for-ios-server-setup/
Update 13th April 2012 : After more research, I think the real relevant code I need to display in this question is this ...
This is where the TURNSocket attempts to connect
XMPPJID *jid = [XMPPJID jidWithString:#"myFriendsUsername#beta.myCompany.co.uk"];
NSLog(#"Attempting TURN connection to %#", jid);
TURNSocket *turnSocket = [[TURNSocket alloc] initWithStream:[self xmppStream] toJID:jid];
[turnSockets addObject:turnSocket];
[turnSocket startWithDelegate:self delegateQueue:dispatch_get_main_queue()];
[turnSocket release];
However, when I debug through the code, in TURNSocket I get to a comment which states that "We were unable to find a single proxy server from our list". This is because the Array 'streamhosts' never gets populated. What could be the issue? Is there some XML somewhere that should tell me the problem? Is the issue likely to be with OpenFire?
The problem is caused if a full jID with a resource is not provided to TurnSocket.m! This is passed in in viewDidLoad of SMChatViewController
e.g Use
friendsUsername#beta.myCompany.co.uk/spark
rather than
friendsUsername#beta.myCompany.co.uk
My progress on this project can be followed here
This is the class method of TURNSocket you call to
populate the proxy candidates of the TURNSocket
stream host. So you should put streamhost back to
what it was before stream-host.
+ (void)setProxyCandidates:(NSArray *)candidates;
[TURNSocket setProxyCandidates:#["host1.somedomain.com", #"host2.someotherdomain.com"]];
In processRequestResponse.m in TurnSocket, the name of the streamhost element wasn't what OpenFire was giving me. I have changed it from this
NSXMLElement *streamhostUsed = [query elementForName:#"streamhost-used"];
to this
NSXMLElement *streamhostUsed = [query elementForName:#"streamhost"];
However, I now have a new error which I am starting a new question for ... OpenFire/XMPP 503 service-unavailable error (XEP-0065 using iOS XMPPFramework)
Update 20/4/2012 : I now believe this answer is wrong! If it was working correctly, streamhostUsed would be there, rather than streamhost with an error!