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);
}
}
}
}];
}
Related
I am adding share functionalities on my facebook app.Like When a "saying" is selected there is a button for sharing that "saying" on facebook.And while clicking this button I can only see the shared saying on my facebook page,there isnt any information about my ios app.How can I make everyone knows that this saying is shared through my iOS app? Please help me....
I may be a little late. Hope this helps.
You have to use the Accounts framework and the Social framework to share with your app name.
First make sure you have set up your App on Facebook correctly. Then you can use the Facebook App ID to share your posts through your app.
Here is a sample code that shows you how to use the Accounts framework with the Social Framework :
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// At first, we only ask for the basic read permission
NSArray * permissions = #[#"email"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"275485699289493", ACFacebookAppIdKey, permissions, ACFacebookPermissionsKey, ACFacebookAudienceOnlyMe, ACFacebookAudienceKey, nil];
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
//it will always be the last object with single sign on
self.facebookAccount = [accounts lastObject];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
/**
* The user granted us the basic read permission.
* Now we can ask for more permissions
**/
NSArray *readPermissions = #[ #"publish_actions"];
[dict setObject:readPermissions forKey: ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if(granted && error == nil) {
NSDictionary *parameters = #{#"message": #"This Should Work Perfectly !! "};
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest *feedRequest = [SLRequest
requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:feedURL
parameters:parameters];
feedRequest.account = self.facebookAccount;
[feedRequest performRequestWithHandler:^(NSData *responseData,
NSHTTPURLResponse *urlResponse, NSError *error)
{
// Handle response
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
}
I'm doing an App and I want to allow users to register from Fb, so, I thought of getting name, email and gender from Facebook, but cannot find a way to fetch the data, if anyone could help.
Here's an example of my code:
// extract the id's for which we will request the profile
NSArray *fbids = [NSArray arrayWithObjects:#"name",#"email",#"gender", nil];
// create the connection object
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
// for each fbid in the array, we create a request object to fetch
// the profile, along with a handler to respond to the results of the request
for (NSString *fbid in fbids) {
// create a handler block to handle the results of the request for fbid's profile
FBRequestHandler handler =
^(FBRequestConnection *connection, id result, NSError *error) {
// output the results of the request
[self requestCompleted:connection forFbID:fbid result:result error:error];
};
// create the request object, using the fbid as the graph path
// as an alternative the request* static methods of the FBRequest class could
// be used to fetch common requests, such as /me and /me/friends
FBRequest *request = [[FBRequest alloc] initWithSession:FBSession.activeSession
graphPath:fbid];
// add the request to the connection object, if more than one request is added
// the connection object will compose the requests as a batch request; whether or
// not the request is a batch or a singleton, the handler behavior is the same,
// allowing the application to be dynamic in regards to whether a single or multiple
// requests are occuring
[newConnection addRequest:request completionHandler:handler];
}
// FBSample logic
// Report any results. Invoked once for each request we make.
- (void)requestCompleted:(FBRequestConnection *)connection
forFbID:fbID
result:(id)result
error:(NSError *)error {
// not the completion we were looking for...
if (self.requestConnection &&
connection != self.requestConnection) {
return;
}
// clean this up, for posterity
self.requestConnection = nil;
NSString *nombre;
NSString *localizacion;
NSString *genero;
NSString *cumpleanyos;
NSString *email;
if (error) {
// error contains details about why the request failed
nombre = error.localizedDescription;
} else {
// result is the json response from a successful request
NSDictionary *dictionary = (NSDictionary *)result;
// we pull the name property out, if there is one, and display it
nombre = (NSString *)[dictionary objectForKey:#"name"];
localizacion = (NSString *)[dictionary objectForKey:#"location"];
genero = (NSString *)[dictionary objectForKey:#"gender"];
cumpleanyos = (NSString *)[dictionary objectForKey:#"birthday"];
email = (NSString *)[dictionary objectForKey:#"email"];
}
}
I think the problem is with:
NSArray *fbids = [NSArray arrayWithObjects:#"name",#"email",#"gender", nil];
You'll need to use "FaceBook User Ids" try with:
NSString *camposUsuario = #"4,6";
NSArray *fbids = [camposUsuario componentsSeparatedByString:#","];
In this case "4" and "6" are "FaceBook User Ids".
If you want Request information for a specific user you need to know his "FaceBook User Id".
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.
at the moment I am trying to implement the Facebook API in one of my iOS Apps.
But now I have a small problem.
I can access my user information or my friend list but I have a problem to get all my objects of my inbox. Of course I set the access token. But now I don't know how to get the messages (or called threads in Facebook see: http://developers.facebook.com/docs/reference/api/thread/)
- (NSArray*) getUserMessages {
NSArray *result = [[NSArray alloc] initWithObjects:#"test", nil];
[facebook requestWithGraphPath:#"me/threads" andDelegate:self];
return result;
}
I also get a callback of my delegate method:
- (void) request:(FBRequest *)request didLoad:(id)result {
NSLog(#"%#", [result description]);
}
I would be kind if someone could help me!
Best regards
xen
necessarily set "read_mailbox" in read permissions
-(void)readFBMessages{
[FBRequestConnection startWithGraphPath:#"/me/threads"
parameters:nil
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
self.tableData = result[#"data"];
[self.tableSearch reloadData];
}];
}
I am currently in the process of building a native Google Reader iPhone application similar to the successful application "Reeder for iPhone", however, with a full Twitter client inbuilt as well.
I have finished the Twitter client and am now struggling to start the Google Reader client. I've browsed through multiple documents and have taken a look at the gdata-objective-client samples, yet I still can't seem to understand what I have to do to accomplish the same functionality as Reeder does.
Basically I want to be able to present the user with a login screen. The user then submits their credentials and the access token and all of that are done behind scenes, like they do with Twitter's xAuth. I then want to push a view controller that shows a UITableView with all the current unread feeds. When the user clicks the UITableViewCell a detailed view is respectively pushed containing the posts content.
Is this possible and if so, how do I go about implementing these features? I would appreciate it if people posted "code snippets" and actually show how they achieve the implementations.
Thanks in advance!
EDIT: It has been brought to my attention that the google app engine isn't needed. The question however, still remains the same. How would I implement Google Reader into my application?
It was so simple. For all those wondering, to connect to Google Reader API, I did the following.
/* Google clientLogin API:
Content-type: application/x-www-form-urlencoded
Email=userName
Passwd=password
accountType=HOSTED_OR_GOOGLE
service=xapi
source = #"myComp-myApp-1.0"
*/
//define our return objects
BOOL authOK;
NSString *authMessage = [[NSString alloc] init];
NSArray *returnArray = nil;
//begin NSURLConnection prep:
NSMutableURLRequest *httpReq = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:GOOGLE_CLIENT_AUTH_URL] ];
[httpReq setTimeoutInterval:30.0];
//[httpReq setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[httpReq setHTTPMethod:#"POST"];
//set headers
[httpReq addValue:#"Content-Type" forHTTPHeaderField:#"application/x-www-form-urlencoded"];
//set post body
NSString *requestBody = [[NSString alloc]
initWithFormat:#"Email=%#&Passwd=%#&service=reader&accountType=HOSTED_OR_GOOGLE&source=%#",
gUserString, gPassString, [NSString stringWithFormat:#"%#%d", gSourceString]];
[httpReq setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding]];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = nil;
NSString *responseStr = nil;
NSArray *responseLines = nil;
NSString *errorString;
//NSDictionary *dict;
int responseStatus = 0;
//this should be quick, and to keep same workflow, we'll do this sync.
//this should also get us by without messing with threads and run loops on Tiger.
data = [NSURLConnection sendSynchronousRequest:httpReq returningResponse:&response error:&error];
if ([data length] > 0) {
responseStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
//NSLog(#"Response From Google: %#", responseStr);
responseStatus = [response statusCode];
//dict = [[NSDictionary alloc] initWithDictionary:[response allHeaderFields]];
//if we got 200 authentication was successful
if (responseStatus == 200 ) {
authOK = TRUE;
authMessage = #"Successfully authenticated with Google. You can now start viewing your unread feeds.";
}
//403 = authentication failed.
else if (responseStatus == 403) {
authOK = FALSE;
//get Error code.
responseLines = [responseStr componentsSeparatedByString:#"\n"];
//find the line with the error string:
int i;
for (i =0; i < [responseLines count]; i++ ) {
if ([[responseLines objectAtIndex:i] rangeOfString:#"Error="].length != 0) {
errorString = [responseLines objectAtIndex:i] ;
}
}
errorString = [errorString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
/*
Official Google clientLogin Error Codes:
Error Code Description
BadAuthentication The login request used a username or password that is not recognized.
NotVerified The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
TermsNotAgreed The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
CaptchaRequired A CAPTCHA is required. (A response with this error code will also contain an image URL and a CAPTCHA token.)
Unknown The error is unknown or unspecified; the request contained invalid input or was malformed.
AccountDeleted The user account has been deleted.
AccountDisabled The user account has been disabled.
ServiceDisabled The user's access to the specified service has been disabled. (The user account may still be valid.)
ServiceUnavailable The service is not available; try again later.
*/
if ([errorString rangeOfString:#"BadAuthentication" ].length != 0) {
authMessage = #"Please Check your Username and Password and try again.";
}else if ([errorString rangeOfString:#"NotVerified"].length != 0) {
authMessage = #"This account has not been verified. You will need to access your Google account directly to resolve this";
}else if ([errorString rangeOfString:#"TermsNotAgreed" ].length != 0) {
authMessage = #"You have not agreed to Google terms of use. You will need to access your Google account directly to resolve this";
}else if ([errorString rangeOfString:#"CaptchaRequired" ].length != 0) {
authMessage = #"Google is requiring a CAPTCHA response to continue. Please complete the CAPTCHA challenge in your browser, and try authenticating again";
//NSString *captchaURL = [responseStr substringFromIndex: [responseStr rangeOfString:#"CaptchaURL="].length];
//either open the standard URL in a browser, or show a custom sheet with the image and send it back...
//parse URL to append to GOOGLE_CAPTCHA_URL_PREFIX
//but for now... just launch the standard URL.
//[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:GOOGLE_CAPTCHA_STANDARD_UNLOCK_URL]];
}else if ([errorString rangeOfString:#"Unknown" ].length != 0) {
authMessage = #"An Unknow error has occurred; the request contained invalid input or was malformed.";
}else if ([errorString rangeOfString:#"AccountDeleted" ].length != 0) {
authMessage = #"This user account previously has been deleted.";
}else if ([errorString rangeOfString:#"AccountDisabled" ].length != 0) {
authMessage = #"This user account has been disabled.";
}else if ([errorString rangeOfString:#"ServiceDisabled" ].length != 0) {
authMessage = #"Your access to the specified service has been disabled. Please try again later.";
}else if ([errorString rangeOfString:#"ServiceUnavailable" ].length != 0) {
authMessage = #"The service is not available; please try again later.";
}
}//end 403 if
}
//check most likely: no internet connection error:
if (error != nil) {
authOK = FALSE;
if ( [error domain] == NSURLErrorDomain) {
authMessage = #"Could not reach Google.com. Please check your Internet Connection";
}else {
//other error
authMessage = [authMessage stringByAppendingFormat:#"Internal Error. Please contact notoptimal.net for further assistance. Error: %#", [error localizedDescription] ];
}
}
//NSLog (#"err localized description %#", [error localizedDescription]) ;
//NSLog (#"err localized failure reasons %#", [error localizedFailureReason]) ;
//NSLog(#"err code %d", [error code]) ;
//NSLog (#"err domain %#", [error domain]) ;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Authentication" message:authMessage delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[alertView show];
[alertView release];
[gUserString release];
[gPassString release];
[gSourceString release];
[authMessage release];
}
}
Obviously I used my own delegates and such, but that is the overall want/feel that I brought to my application.
I'm currently working on pulling the unread feeds/items into a UITableView to display in my RootViewController. I'll update this with more information.
Thanks to all those that tried to help :D
THANK YOU. I knew there was a simple way to log in, but I was having a horrible time figuring it out. Btw for those of you who are copying/pasing the the0rkus's code above - you'll get a few errors. To test it out I added:
NSString *gUserString = #"yourlogin#gmail.com";
NSString *gPassString = #"yourpassword";
NSString *GOOGLE_CLIENT_AUTH_URL = #"https://www.google.com/accounts/ClientLogin?client=YourClient";
NSString *gSourceString = #"YourClient";
Google it, there are lots of blogs out there that describe how to use the Google Reader API. Here's a decent starting point:
http://mindsharestrategy.com/google-reader-api-a-brief-tutorial/