how to implement google chat in iphone app - objective-c

i have searched a lot on the web but can not find the actual sample source code that can help me to get started for google chat implementation , the sample code provided with the xmpp framework also does not tell clearly about it, as it have a sample project of Mac desktop application.
I have been able to show all my friends who are online/ofline/away with the help of sample project(iphoneXmpp) which is provided in the xmppframework, but it also doest tell anything about how to initiate a chat.
Please provide me any sample source code so that i can initialize the google chat in my app.
i am really stuck.
thanks in advance

okey i didnt give up and had some solution after looking into the desktop application of xmpp framework and tried to include it in my iphone app..
here is the code to send message to our chat friend on gmail..
-(void)sendMessage
{
messageStr = [NSString stringWithFormat:#"%#",[msgField text] ];
//messageStr = [NSString stringWithString:#"hello ji....."];
BOOL isEmpty = [ self validateIsEmpty:msgField.text];
if([messageStr length] > 0 && isEmpty == NO )
{
NSXMLElementK *body = [NSXMLElementK elementWithName:#"body"];
[body setStringValue:messageStr];
NSXMLElementK *message = [NSXMLElementK elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:[[user jid] full]];
[message addChild:body];
[[self xmppStream ] sendElement:message];
}
and in didReceiveMessage , i have following code...
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
NSLog(#"---------- xmppStream:didReceiveMessage: ----------");
NSLog(#"--jid---%#", [[user jid] full]);
NSLog(#"--from----%#", [message from]);
//if(![[[user jid] full] isEqual:[message from]]) return;// important when chatting with 2 or more .. and receiving 2 or more messages...
if([message isChatMessageWithBody])
{
NSString *msg = [[message elementForName:#"body"] stringValue];
NSLog(#"mmmmmmmmmmssssssgggg-%#",msg);
[str appendString:[NSString stringWithFormat:#"%#:%#\n\n", [message from], msg]];
[chatBox setText:str];
}
}
i'm able to send/recieve the chat using these two methods but problem is that some times the person's id which i selected from the table view of available online contacts(to whom we can chat with) does'nt receive the message but any other person receives the message..
Cheers!!

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSString *msg = [[message elementForName:#"body"] stringValue];
NSString *from = [[message attributeForName:#"from"] stringValue];
if (msg.length==0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Receiving Message"
message:[NSString stringWithFormat:#"From %#",from]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
if (msg.length!=0) {
NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
[m setObject:msg forKey:#"msg"];
[m setObject:from forKey:#"sender"];
NSLog(#"message received : %#", m);
[_messageDelegate newMessageReceived:m];
}
}
This works great for you, and it will also give you the alert who is sending the message and who wants to chat with you, However I'm just stuck from where should I implement the Logout for the user through which I logged in to iOS SDK.

This tutorial should do the trick : http://mobile.tutsplus.com/tutorials/iphone/building-a-jabber-client-for-ios-server-setup/

Related

Application having trouble when opening with network

I'm building an app that is using the Instagram API to display photos but I'm running into some trouble. The app is crashing when there is no network connection and I have found the code that is causing the problem.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.accessToken = [userDefaults objectForKey:#"accessToken"];
if (self.accessToken == nil) {
[SimpleAuth authorize:#"instagram" options:#{#"scope": #[#"likes"]} completion:^(NSDictionary *responseObject, NSError *error) {
self.accessToken = responseObject[#"credentials"][#"token"];
[userDefaults setObject:self.accessToken forKey:#"accessToken"];
[userDefaults synchronize];
[self refresh];
}];
} else {
[self refresh];
}
I have found that the [self refresh]; is causing the problem in the else block and I tried to replace it with a alert view like this
UIAlertView *networkError = [[UIAlertView alloc] initWithTitle:#"Network Error" message:#"Please connect your device to a network and restart application" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
[networkError show];
However, with this problem I find that if I open the app with a network connection I still get the alert. Any help would be great because I'm still new to Objective C!
Thank you for the help!
I know this code from Treehouse :).
The thing is that the if (self.accessToken == nil) { /.../ } block will only get execute when the app is not authorized using your Instagram credentials.
Once you logged in successfully, it will always execute the code in the else { /.../ } block. If it has connection to Internet, it will do its work, download, display images etc. If you insert the code to display alert, it will always do that because you actually mean that by that code.
If you want to check if there is some connection, you need to do that before all that code, display an error and return instantly if connection is not available. However, the author tried to keep things simple, assuming there is always Internet connection.
Hope it makes you understand it.
This is the some code you can use for checking if there is connection:
// show some activity indicator
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// Do something...
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
NSURL *url = [NSURL URLWithString:#"http://www.apple.com/"];
NSString *s = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding
error:nil];
dispatch_async(dispatch_get_main_queue(), ^{
// hide the activity indicator
self.connected = (s != nil);
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
if (self.isConnected)
{
NSLog(#"self.connected == YES");
}
else
{
NSLog(#"self.connected == NO");
NSString *alertMessage = #"In order to load images, you need an active Internet connection. Please try again later!";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Sorry!"
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
});
});
You obviously need to add a property to you class. You can insert this code:
#interface LDPhotosViewController ()
#property (nonatomic, copy, getter = isConnected) NSString *connected;
#end
at the top of LDPhotosViewController.m file, before the #implementation line.

Retrieve facebook friends & invite them to my iOS app

I am developing an iOS application in which I want to retrieve my facebook friends & send it to server for checking who are already using this app using their email or phone number. Once I get friends who are not using my application then I will show "Invite" button to send an email to their email address with app store link to download the app.
But as per facebook permissions , we can not retrieve the facebook friends email address.
Can anybody know how can I implement this feature in other way ?
Any kind of help is appreciated. Thanks.
you can not retrieve facebook friends email address but you can post on their wall whatever link you want to post i.e. app store link to download the app.
You can give a look to my this thread.
Since facebook does not provide email address so the idea behind this solution to offer is that, you can send invite friend request with the link to your application at AppStore. I have briefly described the steps in link to follow in order to accomplish this case.
Invitation message might look like this:
I would like you to try XYZ game. Here is the link for this
Application at AppStore:
Facebook iOS SDK - get friends list
You can use FB Graph API(/me/invitable_friends) as below for getting non app friends -
// m_invitableFriends - global array which will hold the list of invitable friends
- (void) getAllInvitableFriends
{
NSMutableArray *tempFriendsList = [[NSMutableArray alloc] init];
NSDictionary *limitParam = [NSDictionary dictionaryWithObjectsAndKeys:#"100", #"limit", nil];
[self getAllInvitableFriendsFromFB:limitParam addInList:tempFriendsList];
}
- (void) getAllInvitableFriendsFromFB:(NSDictionary*)parameters
addInList:(NSMutableArray *)tempFriendsList
{
[FBRequestConnection startWithGraphPath:#"/me/invitable_friends"
parameters:parameters
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
NSLog(#"error=%#",error);
NSLog(#"result=%#",result);
NSArray *friendArray = [result objectForKey:#"data"];
[tempFriendsList addObjectsFromArray:friendArray];
NSDictionary *paging = [result objectForKey:#"paging"];
NSString *next = nil;
next = [paging objectForKey:#"next"];
if(next != nil)
{
NSDictionary *cursor = [paging objectForKey:#"cursors"];
NSString *after = [cursor objectForKey:#"after"];
//NSString *before = [cursor objectForKey:#"before"];
NSDictionary *limitParam = [NSDictionary dictionaryWithObjectsAndKeys:
#"100", #"limit", after, #"after"
, nil
];
[self getAllInvitableFriendsFromFB:limitParam addInList:tempFriendsList];
}
else
{
[self replaceGlobalListWithRecentData:tempFriendsList];
}
}];
}
- (void) replaceGlobalListWithRecentData:(NSMutableArray *)tempFriendsList
{
// replace global from received list
[m_invitableFriends removeAllObjects];
[m_invitableFriends addObjectsFromArray:tempFriendsList];
//NSLog(#"friendsList = %d", [m_invitableFriends count]);
[tempFriendsList release];
}
For Inviting non app friend -
you will get invite tokens with the list of friends returned by me/invitable_friends graph api. You can use these invite tokens with FBWebDialogs to send invite to friends as below
- (void) openFacebookFeedDialogForFriend:(NSString *)userInviteTokens {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
userInviteTokens, #"to",
nil, #"object_id",
#"send", #"action_type",
actionLinksStr, #"actions",
nil];
[FBWebDialogs
presentRequestsDialogModallyWithSession:nil
message:#"Hi friend, I am playing game. Come and play this awesome game with me."
title:nil
parameters:params
handler:^(
FBWebDialogResult result,
NSURL *url,
NSError *error)
{
if (error) {
// Error launching the dialog or sending the request.
NSLog(#"Error sending request : %#", error.description);
}
else
{
if (result == FBWebDialogResultDialogNotCompleted)
{
// User clicked the "x" icon
NSLog(#"User canceled request.");
NSLog(#"Friend post dialog not complete, error: %#", error.description);
}
else
{
NSDictionary *resultParams = [g_mainApp->m_appDelegate parseURLParams:[url query]];
if (![resultParams valueForKey:#"request"])
{
// User clicked the Cancel button
NSLog(#"User canceled request.");
}
else
{
NSString *requestID = [resultParams valueForKey:#"request"];
// here you will get the fb id of the friend you invited,
// you can use this id to reward the sender when receiver accepts the request
NSLog(#"Feed post ID: %#", requestID);
NSLog(#"Friend post dialog complete: %#", url);
}
}
}
}];
}

ABAddressBookGetPersonCount returns -1 in iOS

I am running into a situation where ABAddressBookGetPersonCount is returning -1. The tester assures me there contacts do exist in the address book. All the handsets are running iOS 6.0.1.
Here's the code:
NSMutableDictionary *myAddressBook = [[NSMutableDictionary alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
int numEntries = ABAddressBookGetPersonCount(addressBook);
if (numEntries == 0)
{
NSString *title = NSLocalizedString(#"error", nil);
NSString *description = NSLocalizedString(#"error_empty_contacts", nil);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:description
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return;
}
NSLog(#"emails: found %d", numEntries);
I am not able to reproduce this on any of my handsets, but the tester has tried on 3 handsets. It works properly on an iPhone 5, but not on a 4 or 3;
I can't find any docs that indicate what a value of -1 means. I'm assuming it's an error of some kind, but what?
Under iOS 6, this code isn't valid. You have to verify that your app has permission to access the address book. Most likely, the -1 is an indication that the app has no permission (or an unknown permission state) on those devices.
From the docs for ABAddressBookRequestAccessCompletionHandler:
CFErrorRef myError = NULL;
ABAddressBookRef myAddressBook = ABAddressBookCreateWithOptions(NULL, &myError);
APLViewController * __weak weakSelf = self; // avoid capturing self in the block
ABAddressBookRequestAccessWithCompletion(myAddressBook,
^(bool granted, CFErrorRef error) {
if (granted) {
NSArray *theSmiths = CFBridgingRelease(
ABAddressBookCopyPeopleWithName(myAddressBook,
CFSTR("Smith")
)
);
weakSelf.numberOfSmiths = [theSmiths count];
} else {
// Handle the error
}
});
CFRelease(myAddressBook);
If you need to support iOS 5.x or 4.x you need to properly check for the existence of the new methods.

Upload photo using new iOS Facebook SDK API (3.0)

How can I upload a photo to facebook from an iOS app using their new API/SDK? I've already tried and I'm not getting anywhere, just keep running in circles. Here is the code I currently have:
-(void)dataForFaceboo{
self.postParams =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
self.uploadPhoto.image, #"picture", nil];
}
-(void)uploadToFacebook{
[self dataForFacebook];
NSLog(#"Going to facebook: %#", self.postParams);
// Hide keyboard if showing when button clicked
if ([self.photoCaption isFirstResponder]) {
[self.photoCaption resignFirstResponder];
}
// Add user message parameter if user filled it in
if (![self.photoCaption.text
isEqualToString:kPlaceholderPostMessage] &&
![self.photoCaption.text isEqualToString:#""])
{
[self.postParams setObject:self.photoCaption.text forKey:#"message"];
}
[FBRequestConnection startWithGraphPath:#"me/feed"
parameters:self.postParams
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat:
#"Posted action, id: %#",
[result objectForKey:#"id"]];
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil] show];
}];
}
Your code is fine, some slight changes to be done:
add the image to the dictionary in NSData format, like
[params setObject:UIImagePNGRepresentation(_image) forKey:#"picture"];
and change the graph path to "me/photos" instead of "me/feed"
Make these changes, it worked for me.
Remember you need to use "publish_actions" permissions.
"me/photos" is meant for the photo actually be in the "Photo's" list on your Facebook profile. "me/feed" is just a post on the timeline.

GameKit Server/Client

I have been trying to implement the GameKit Framework for bluetooth connection and want to use a Server/Client relationship to reduce lag and be able to distinguish between to connected devices. I found this thread and it is similar to what I am trying to do, but the code doesn't work for me. Here is what I have:
Connect Method:
-(IBAction) btnConnect:(id) sender {
if(sender == server){
[self.currentSession initWithSessionID:#"BT" displayName:nil sessionMode:GKSessionModeServer];
currentSession.available == YES;
NSLog(#"Setup Server");
}else{
[self.currentSession initWithSessionID:#"BT" displayName:nil sessionMode:GKSessionModeClient];
currentSession.available == YES;
NSLog(#"Setup Client");
}
currentSession.delegate = self;
currentSession.disconnectTimeout = 0;
[currentSession setDataReceiveHandler:self withContext:nil];
[client setHidden:YES];
[server setHidden:YES];
[disconnect setHidden:NO];
}
didChangeState:
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
NSLog(#"didChangeState was called with status: %#.", state);
switch (state)
{
case GKPeerStateConnected:
NSLog(#"connected");
break;
case GKPeerStateDisconnected:
NSLog(#"disconnected");
[self.currentSession release];
currentSession = nil;
[connect setHidden:NO];
[disconnect setHidden:YES];
break;
case GKPeerStateAvailable:
NSLog(#"Server is Available, Presenting UIALert...");
NSLog(#"%#", peerID);
peerName = [session displayNameForPeer:peerID];
NSLog(#"%#", peerName);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Server Available!" message:[NSString stringWithFormat:#"The Server %# is Available, Would you like to Connect?", peerName] delegate:self cancelButtonTitle:#"Decline" otherButtonTitles:#"Accept", nil];
[alert show];
[alert release];
if(selection == #"accept"){
[session connectToPeer:peerID withTimeout:15];
session.available = NO;
}else{
}
break;
}
}
didReceiveConnectionRequest:
- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID{
NSLog(#"Recieved Connection Request");
NSLog(#"%#", peerID);
peerName = [session displayNameForPeer:peerID];
NSLog(#"%#", peerName);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Connection Request" message:[NSString stringWithFormat:#"The Client %# is trying to connect.", peerName] delegate:self cancelButtonTitle:#"Decline" otherButtonTitles:#"Accept", nil];
[alert show];
[alert release];
if(selection == #"accept"){
[session acceptConnectionFromPeer:peerID error:nil];
}else{
[session denyConnectionFromPeer:peerID];
}
}
I think I have this all setup right, but the didChangeState isn't getting called to inform the user that another device is available. Am I missing something or should I try to use a different method. Thanks for any help
currentSession.disconnectTimeout = 0;
The disconnect timeout is a time in seconds that peers should wait before disconnecting unresponsive peers. You don't want this to be 0. The default is 20 seconds, you should leave it there or say like 10 seconds. I actually don't set this in my GameKit code and it works well.
Also, it might help to post your entire implementation class somewhere. We'll need to make sure you are implementing GKSessionDelegate, e.g.:
#interface SomeObject : NSObject <GKSessionDelegate>
Also, you're setting up a Peer-2-Peer above. You said you were trying to do client/server. If so you should start the client session with a mode of GKSessionModeClient and server as GKSessionModePeer.
Lastly...are you testing this on actual devices or with a device and simulator? Don't forget that simulator and first gen iPhones and touches do not support bluetooth. So you'll have to have everyone involved connected to the same wireless network for anything to happen.
What are you seeing in the console when you start up your debug session?