As an incident of a user taking some action in my app, I want to post an image to Facebook on their behalf. Let's assume the user has already granted me publish_actions permission in class LoginVC (one time permission is used for ad infinitum posting in the future). Then at some in the future, in ActionVC, I want to publish a photo to Facebook. How do I do that? Here is the method I need to implement:
- (void)publishPhoto:(UIImage *)image
{
//what goes in here?
}
So far I have been looking at the samples from Facebook. The closest I come is the following, but it seems to be using a Dialog. But I don't want the user to "know" that the photo is being posted. They already granted the permission and I want the posting to happen without their knowledge as it were. So some other action has triggered the call to publish...
For reference, the code from the Facebook sample looks like this
- (void)publishPhoto:(UIImage *)image
{
BOOL canPresent = [FBDialogs canPresentShareDialogWithPhotos];
NSLog(#"canPresent: %d", canPresent);
FBPhotoParams *params = [[FBPhotoParams alloc] init];
params.photos = #[image];
BOOL isSuccessful = NO;
if (canPresent) {
FBAppCall *appCall = [FBDialogs presentShareDialogWithPhotoParams:params
clientState:nil
handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if (error) {
NSLog(#"Error: %#", error.description);
} else {
NSLog(#"Success!");
}
}];
isSuccessful = (appCall != nil);
}
if (!isSuccessful) {
[self performPublishAction:^{
FBRequestConnection *connection = [[FBRequestConnection alloc] init];
connection.errorBehavior = FBRequestConnectionErrorBehaviorReconnectSession
| FBRequestConnectionErrorBehaviorAlertUser
| FBRequestConnectionErrorBehaviorRetry;
[connection addRequest:[FBRequest requestForUploadPhoto:image]
completionHandler:^(FBRequestConnection *innerConnection, id result, NSError *error) {
[self showAlert:#"Photo Post" result:result error:error];
if (FBSession.activeSession.isOpen) {
self.buttonPostPhoto.enabled = YES;
}
}];
[connection start];
self.buttonPostPhoto.enabled = NO;
}];
}
}
Sorry if this question seems too easy, but I am a newbie to Facebook SDK integration
Generally you definitely want the user to be aware that something is being posted on their behalf, but to answer your question, if they've already granted you publish permissions, then you can use the code in the second "if" statement that you posted above, where it calls FBRequest requestForUploadPhoto:
Related
My facebook login with parse is working perfectly with no issues but the access token that is generated is not showing permission for friendlist although I gave that permission at the time of login. I came to know when I used facebook Graph API 'Friendlists'(fbID/friendlists) and the response array is empty. So, also run Graph API explorer with the same access token generated. It does not show me any error and data array is same empty and a debug message with
"The field 'friendlists' is only accessible on the User object after the user grants the 'read_custom_friendlists' permission"
This is the method I am using
WLLoginViewController *login = [[WLLoginViewController alloc]init];
login.fields = PFLogInFieldsFacebook;
NSArray *permission = [[NSArray alloc]initWithObjects:#"email",#"read_custom_friendlists",#"publish_actions",#"user_location",#"user_hometown",#"user_website",#"user_about_me",#"user_photos",#"user_friends",#"read_custom_friendlists", nil];
login.facebookPermissions = permission;
WLLoginViewController has inherited PFUserLoginManager and I am calling it from some other class.
- (void)logInViewController:(PFLogInViewController *)logInController didLogInUser:(PFUser *)user {
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"permissions%#",logInController.facebookPermissions);
if(result) {
if ([result valueForKey:#"hometown"]) {
NSString *nn = [[result valueForKey:#"hometown"] valueForKey:#"name"];
[user setValue:[[result valueForKey:#"hometown"] valueForKey:#"name"] forKey:#"hometown"];
}
if ([result valueForKey:#"location"]) {
[user setValue:[[result valueForKey:#"location"] valueForKey:#"name"] forKey:#"location"];
}
[user setObject:[result valueForKey:#"id"] forKey:kWLUser_FacebookId];
[user setObject:[result valueForKey:#"name"] forKey:kWLUser_Name];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if([PFInstallation currentInstallation]) {
// save in background current installation.
[[PFInstallation currentInstallation] setObject:user forKey:#"user"];
[[PFInstallation currentInstallation]saveInBackground];
}
}];
[[ParseManager sharedInstance]saveDeviceToken:[[NSUserDefaults standardUserDefaults]objectForKey:#"DeviceToken"]];
[self dismissViewControllerAnimated:YES completion:nil];
}else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Could not login" message:#"Could not login to facebook, please try again" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
}];
}
This is the method which is which is running when the user return to the app from facebook.The nslog in the code is showing the permission perfectly which I gave.
And finally this is the method for handling facebook request
-(void)handleFacebookFriendsRequest {
NSString *queryParams = #"id,name,picture.width(350).height(250),location,hometown,likes.limit(100000),statuses.limit(1),languages";
[queryParams stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#",[FBSession activeSession].permissions);
NSLog(#"%#",[[FBSession activeSession].permissions description]);
NSLog(#"%#",[FBSession activeSession].accessTokenData.accessToken);
[FBRequestConnection startWithGraphPath:[NSString stringWithFormat:#"me/friends?fields=%#",queryParams] completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
//change For getting everything out
NSLog(#"%#",[result objectForKey:#"data"]);
[[ApplicationDataModel sharedInstance]setFacebookFriendsList:[result objectForKey:#"data"]];
[self facebookRequestDidLoad:result];
} else {
[self facebookRequestDidFailWithError:error];
}
}];
}
I am stuck badly need help. Thanks in advance
The read_custom_friendlists is not a default permission, as a result you have to go through the approval process for this feature (https://developers.facebook.com/docs/facebook-login/permissions/v2.2)
To submit items for approval go to:
developers.facebook.com -> My Apps -> Status & Review
Caveat: "People listed in the Roles section of your App Dashboard - including Admins, Developers and Testers - can grant any permission without review. If only people in these Roles will use your app, you don't need to submit it for Login Review."(https://developers.facebook.com/docs/apps/faq)
I'm trying to share to Facebook using code from their iOS game tutorial. The dialog pops up and the image and text I specified is present, but when I hit "Send" the loading bar appears, doesn't load, then I am redirected to my app. No errors are printed to the console and the app does not crash.
When I go on Facebook to check if the message has posted, I get the following:
"Oops, Something Went Wrong. There was a problem posting your status. We've logged the error and will look into it."
I've used this code in the previous app and it worked perfectly fine. I've updated the Facebook ID, Facebook Display Name, and URL Scheme in the plist.
Here is the code:
FacebookHandler class (derived from Facebook tutorial)
#import "FacebookHandler.h"
#implementation FacebookHandler
+ (void) Facebook_CreateNewSession
{
// initialize Facebook
FBSession* session = [[FBSession alloc] init];
[FBSession setActiveSession: session];
}
+ (void) Facebook_Login
{
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"email",
nil];
// Attempt to open the session. If the session is not open, show the user the Facebook login UX
[FBSession openActiveSessionWithReadPermissions:permissions allowLoginUI:true completionHandler:^(FBSession *session, FBSessionState status, NSError *error)
{
// Did something go wrong during login? I.e. did the user cancel?
if (status == FBSessionStateClosedLoginFailed || status == FBSessionStateCreatedOpening) {
// If so, just send them round the loop again
[[FBSession activeSession] closeAndClearTokenInformation];
[FBSession setActiveSession:nil];
[self Facebook_CreateNewSession];
}
else
{
}
}];
}
+ (void) Facebook_PostToNewsFeedWithTitle:(NSString*)title withCaption:(NSString*)caption withDescription:(NSString*)description withLink:(NSString*)link withPictureURL:(NSString*)picURL
{
// check if user is logged in
if ([FBSession activeSession] == nil)
{
[FacebookHandler Facebook_CreateNewSession];
[FacebookHandler Facebook_Login];
}
// This function will invoke the Feed Dialog to post to a user's Timeline and News Feed
// It will attemnt to use the Facebook Native Share dialog
// If that's not supported we'll fall back to the web based dialog.
NSString *linkURL = link;
NSString *pictureURL = picURL;
// Prepare the native share dialog parameters
FBShareDialogParams *shareParams = [[FBShareDialogParams alloc] init];
shareParams.link = [NSURL URLWithString:linkURL];
shareParams.name = title;
shareParams.caption= caption;
shareParams.picture= [NSURL URLWithString:pictureURL];
shareParams.description = description;
if ([FBDialogs canPresentShareDialogWithParams:shareParams]){
[FBDialogs presentShareDialogWithParams:shareParams
clientState:nil
handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if(error) {
NSLog(#"Error publishing story.");
} else if (results[#"completionGesture"] && [results[#"completionGesture"] isEqualToString:#"cancel"]) {
NSLog(#"User canceled story publishing.");
} else {
NSLog(#"Story published.");
}
}];
}else {
// Prepare the web dialog parameters
NSDictionary *params = #{
#"name" : shareParams.name,
#"caption" : shareParams.caption,
#"description" : shareParams.description,
#"picture" : pictureURL,
#"link" : linkURL
};
// Invoke the dialog
[FBWebDialogs presentFeedDialogModallyWithSession:nil
parameters:params
handler:
^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
NSLog(#"Error publishing story.");
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
NSLog(#"User canceled story publishing.");
} else {
NSLog(#"Story published.");
}
}}];
}
}
#end
My Call
[FacebookHandler Facebook_PostToNewsFeedWithTitle:title withCaption:caption withDescription:description withLink:link withPictureURL:picURL];
UPDATE
It seems to be a problem with the Facebook app. When trying it on a device with Facebook uninstalled, I am asked to log in and then it posts successfully. However, if Facebook is installed, it doesn't post.
I fix it by manually typing the "URL types" key at the plist file.
Don't copy paste the plist values from another plist file - it's Apple's bug!!!
I'm trying to present the facebook share dialog from my iOS app.
This code opens the facebook app and shows the dialog:
FBShareDialogParams* params = [[FBShareDialogParams alloc] init];
params.link = urlToShare;
params.name = #"Test";
params.description = #"Description";
params.picture = [NSURL URLWithString:FB_IMG_URL];
BOOL canPresentShareDialog = [FBDialogs canPresentShareDialogWithParams:params];
if (canPresentShareDialog) {
[FBDialogs presentShareDialogWithParams:params clientState:nil handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if (error) {
if ([FBErrorUtility shouldNotifyUserForError:error]) {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Facebook-Error!" message:[FBErrorUtility userMessageForError:error] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
} else {
NSLog(#"SUCCESS");
}
}];
}
In the completion handler I want to know if the user canceled the action. The results dictionary should tell me that. However I only get didComplete=YES in the dictionary but not a completionGesture. The NSError object is always nil.
The results dictionary is explained here: https://developers.facebook.com/ios/share-dialog/
So the problem is I can't tell if the post was successful or not.
Is something wrong with my code?
As stated in the doc, the "completionGesture" field is "only available if the user logged into your app".
So if the user has never used Facebook login with your app before, you will not get that field, and will only see the "didComplete" field.
If I am not wrong then you want to know if user is unable to post the data on facebook because of some error or because he pressed cancel button. If this is the case then use the code given below
[FBDialogs presentShareDialogWithParams:shareParams
clientState:nil
handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if(error) {
NSLog(#"Error publishing story.");
} else if (results[#"completionGesture"] && [results[#"completionGesture"] isEqualToString:#"cancel"]) {
NSLog(#"User canceled story publishing.");
} else {
NSLog(#"Story published.");
}
}];
its been taken from Facebook Developer Reference. Let me know if it helps. Thanks
I'm new to facebook SDK.
Last time I used facebook IOS SDK 3.0 and posting image through graph API. It is working but now it's not. I upgraded to 3.1 but still, it always return HTTP ERROR 200. Is there anyone can help me?
this is the code
- (void) facebookPostPhoto:(UIImage *)photo withMessage:(NSString *)msg withOkAction:(SEL)okAction andNGAction:(SEL)ngAction withTarget:(id)target {
ok = okAction;
ng = ngAction;
curView = target;
NSMutableDictionary *params;
params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
UIImageJPEGRepresentation(photo, 90), #"source",
msg, #"message",
nil];
if ([FBSession.activeSession.permissions indexOfObject:FacebookPermission_3] == NSNotFound) {
NSLog(#"permission not found");
// No permissions found in session, ask for it
[FBSession.activeSession reauthorizeWithPublishPermissions:[NSArray arrayWithObjects:FacebookPermission_1, FacebookPermission_3, nil] defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *session, NSError *error)
{
// If permissions granted, publish the story
if (!error) [self initPostFacebookWithParams:params];
}];
} else {
[self initPostFacebookWithParams:params];
} }
- (void)initPostFacebookWithParams:(NSMutableDictionary *)params {
[FBRequestConnection startWithGraphPath:#"me/photos" parameters:params HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"ERROR : %#", error.localizedDescription);
if (!error) {
NSLog(#"Facebook Post Success..");
if (ok && curView) {
[curView performSelector:ok];
}
} else {
NSLog(#"Facebook Post Failed..");
if (ng && curView) {
[curView performSelector:ng withObject:error];
}
}
}]; }
I appreciate your fast response and help! Thank You!!
I think it's either facebook upload's server is down or there is a new policy about image size. When I down sized the image to 320x320 it returns no error, sometimes error too by the way.
So for those who see this question, try to resize your image to smaller size.
Some form of this has been asked/answered before but I'm still pretty hazy on the issue. I'm trying to post to a friends feed but keep getting "error com.facebook.sdk code = 5" errors when trying to use startWithGraphPath: from the new FB SDK for ios. The FBSession is active and open and the access_token appears to be correct... Here's some code:
-(void)inviteUser:(NSString *)whoever {
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
// No permissions found in session, so ask for it
[FBSession.activeSession reauthorizeWithPublishPermissions:[NSArray arrayWithObject:#"publish_actions"] defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *session, NSError *error) {
if (!error){
[self sendInvite:whoever];
}
}
}];
}
-(void) sendInvite:(NSString *)whoever {
NSMutableDictionary *params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"A name of something", #"name",
nil];
[FBRequestConnection
startWithGraphPath:[NSString stringWithFormat:#"%#/feed", whoever]
parameters:params
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 = #"Posted successfully.";
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil]
show];
}];
I'm still new at this, and am probably missing something basic. But I'm just not seeing it.
Fixed it. I think there were two problems:
Not having the session properly communicated inside the app (i.e. I had the FBSession open in a loginController, but not in the sendInvite controller <- not the exact names, obviously). As a result, the access_token actually wasn't active. I should have followed the FB docs and put the FBSession methods in the appdelegate.
I was using "publish_action" permissions when I believe I should have been using "publish_stream."
Works smoothly with these two changes. I do have a follow-up question, though: how to post on someone else's wall using the new SDK's native share dialog? I'll probably ask this as a separate question.