I'm facing the following problems with my iOS app:
While publishing to user's friend's wall, using iOS app I'm getting the error "com.facebook.sdk error 5".
The app is asking to login every time when I check for "FBSession.activeSession.isOpen".
Everything was working fine before. But since I've changed my app ID (as now I have to use different Facebook app). I'm getting the error.
I've done some research on this and found some solutions. Ive tried them all but nothing works.
I've written the following code to login to Facebook:
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
comingfromFB = YES;
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"friends_birthday",
nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
}
And the following code for publishing story:
if ([FBSession.activeSession.permissions
indexOfObject:#"publish_actions"] == NSNotFound) {
// No permissions found in session, ask for it
[FBSession.activeSession
reauthorizeWithPublishPermissions:
[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
// If permissions granted, publish the story
[self publishStory];
}
}];
} else {
// If permissions present, publish the story
[self publishStory];
}
When I run the app I get the following error:
Error: HTTP status code: 403
2013-02-05 14:36:47.109 <appname>[1705:c07] Error Domain=com.facebook.sdk Code=5 "The operation couldn’t be completed. (com.facebook.sdk error 5.)" UserInfo=0xaa9af20 {com.facebook.sdk:ParsedJSONResponseKey={
body = {
error = {
code = 200;
message = "(#200) The user hasn't authorized the application to perform this action";
type = OAuthException;
};
};
code = 403;
}, com.facebook.sdk:HTTPStatusCode=403}
Please help me to understand where I'm going wrong.
I've also added some key-value pair to NSUserDefaults. Could that be a possible reason for that?
Thanks.
When you're first showing your view with post button, perhaps you want to check if the session is open and set your post button title according to session state. Assuming your button initially has "Post" title:
[FBSession openActiveSessionWithAllowLoginUI: NO];
if (![FBSession.activeSession isOpen])
{
[self setSendButtonTitle:NSLocalizedString(#"Log in",#"")];
}
Then add the following code to your Post button action:
- (void) send: (UIButton*) sender
{
if (![FBSession.activeSession isOpen])
{
[FBSession openActiveSessionWithPublishPermissions: [NSArray arrayWithObjects: #"publish_stream", nil]
defaultAudience: FBSessionDefaultAudienceEveryone
allowLoginUI: YES
completionHandler: ^(FBSession *session,
FBSessionState status,
NSError *error)
{
if (error)
{
NSLog(#"error");
}
else
{
[FBSession setActiveSession:session];
[self setSendButtonTitle: NSLocalizedString(#"Post",#"")];
}
}];
return;
}
// here comes the code you use for sending the message
}
So if the user presses send and the app is not authorized, it will perform a login operation and change your Post button title from "Log in" to "Post". Then the user will be able to post the message by pressing the button once again.
Hope it helps
Related
In my app I want to post a image on my wall however I think i miss something. I did lots of research and end up with that code. Actually it sometimes working but generally when the code is running since there is no session with publish_action permission, second part of the code is working but the problem is I always get error log at the second part, so I cant proceed...Do you have any idea why I cant open active session with publish permissions?
if ([[FBSession activeSession]isOpen]) {
/*
* if the current session has no publish permission we need to reauthorize
*/
if ([[[FBSession activeSession]permissions]indexOfObject:#"publish_actions"] == NSNotFound) {
[[FBSession activeSession] requestNewPublishPermissions:[NSArray arrayWithObject:#"publish_action"] defaultAudience:FBSessionDefaultAudienceOnlyMe
completionHandler:^(FBSession *session,NSError *error){
action();
}];
}else{
[self publishStory];
}
}else{
/*
* open a new session with publish permission
*/
[FBSession openActiveSessionWithPublishPermissions:[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceOnlyMe
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (!error && status == FBSessionStateOpen) {
[self publishStory];
}else{
NSLog(#"error");
}
}];
}
In the first part of the code when you are requesting new publish permissions you have
[NSArray arrayWithObject:#"publish_action"] ....
If i am not not mistaken I think that should be [NSArray arrayWithObject:#"publish_actions"]
Here is code snip from facebook docs
https://developers.facebook.com/docs/technical-guides/iossdk/errors/
// Method that requests permissions needed to make the API call.
- (void)requestPermissionCallAPI {
[FBSession.activeSession
requestNewPublishPermissions:[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceEveryone
completionHandler:^(FBSession *session, NSError *error) {
if (error) {
// Handle new permissions request errors
[self handleRequestPermissionError:error];
} else {
// Make API call
...
}
}];
}
Thanks for reading!
I'm trying to create a Facebook request to enable the user to invite his friends to the app.
NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:nil];
[FBWebDialogs
presentRequestsDialogModallyWithSession:nil
message:#"Learn how to make your iOS apps social."
title:#"Test"
parameters:params
handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
// Error launching the dialog or sending the request.
NSLog(#"Error sending request.");
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
// User clicked the "x" icon
NSLog(#"User canceled request.");
} else {
// Handle the send request callback
NSDictionary *urlParams = [self parseURLParams:[resultURL query]];
if (![urlParams valueForKey:#"request"]) {
// User clicked the Cancel button
NSLog(#"User canceled request.");
} else {
// User clicked the Send button
NSString *requestID = [urlParams valueForKey:#"request"];
NSLog(#"Request ID: %#", requestID);
}
}
}
}];
}
This is pretty much a clean copy of the Facebook docs code. And it works up to a point
The user can choose the friends and the request goes away and gets received by the friends and it shows up as a notification - everything fine so far.
The problem is that when I try to get the response from the "handler" the resultURL is nil and does not contain anything. And after that I get the log message "User canceled request".
Why don't I get anything back? The main reason that I need this is that I need to know which friends the request was sent to.
Thank you for any help!
Seems like you're passing an nil empty session to presentRequestsDialogModallyWithSession
Use FBSession.activeSession instead and check you have enough permissions to run the request (although if not, you would be getting another different error)
I think you are not having a session opened..please try to use this to open the session.
if (!FBSession.activeSession.isOpen) {
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
}];
}
I'm using die Facebook SDK 3.1.1 to implement FB Connect in my iOS application. This works fine in the simple case with either the new FB integration (logged in on iOS) or falling back to the normal authorization via web view (I do not have the native Facebook application installed in both cases).
The problem occurs when I switch the account on iOS level. Logging out and logging in with a different FB user account.
To log in/authorize I perform:
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
If then get a FBSessionStateClosedLoginFailed every time even though I perform a closeAndClearTokenInformation when that state is reached:
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
NSLog(#"Session State Changed: %u", [[FBSession activeSession] state]);
switch (state) {
case FBSessionStateOpen:
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
NSLog(#"FBSessionStateClosedLoginFailed ERROR: %#", [error description]);
[[FBSession activeSession] closeAndClearTokenInformation];
break;
default:
break;
}
However, I receive the same state on every retry. My log says the following:
FBSDKLog: FBSession **INVALID** transition from FBSessionStateCreated to FBSessionStateClosed
FBSDKLog: FBSession transition from FBSessionStateCreated to FBSessionStateCreatedOpening
FBSDKLog: FBSession transition from FBSessionStateCreatedOpening to FBSessionStateClosedLoginFailed Session State Changed: 257
FBSessionStateClosedLoginFailed TOKEN: (null)
FBSessionStateClosedLoginFailed ERROR: Error Domain=com.facebook.sdk Code=2 "The operation couldn’t be completed. (com.facebook.sdk error 2.)" UserInfo=0xb24cc20 {com.facebook.sdk:ErrorLoginFailedReason=com.facebook.sdk:ErrorLoginFailedReason}
Can anyone reproduce this or has any idea where the problem might lie?
Another answer gives a way to manually resync the device with the server. I defined a method called fbRsync to call this code. Make sure to #import <Accounts/Accounts.h> in your implementation file and then define this method:
-(void)fbResync
{
ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) && (accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) ){
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
id account;
if (fbAccounts && [fbAccounts count] > 0 && (account = [fbAccounts objectAtIndex:0])){
[accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
//we don't actually need to inspect renewResult or error.
if (error){
}
}];
}
}
I then call fbResync if openActiveSessionWithReadPermissions yields an error:
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
if(error)
{
NSLog(#"Session error");
[self fbResync];
[NSThread sleepForTimeInterval:0.5]; //half a second
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
}
else
[self sessionStateChanged:session state:state error:error];
}];
The half a second delay is likely unnecessary, but it currently gives me piece of mind.
This seems to solve the problem for me. I can now switch between Facebook accounts and am able to log in. Yay!
I had the same problem. Check that your FB App is enabled in Settings -> Facebook.
Mine was disabled (even though I don't remember disabling it) and once I enabled it, it was fixed.
In my test process, I've added and removed my FB App several times from my FB Account, which is linked with my iPhone. It may explain why, magically, my app was disabled.
In ios 6 with fb sdk 3.1.1. Please pass permissions param as "nil or email" in "[FBSessio openActiveSessionWithReadPermissions..." method. Here my code it was works great.
#define IOS_NEWER_OR_EQUAL_TO_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 6.0 )
-(void)showFBLogin
{
[FBSession.activeSession closeAndClearTokenInformation];
NSArray *permissions = [NSArray arrayWithObjects:#"email, publish_actions, publish_stream", nil];
#ifdef IOS_NEWER_OR_EQUAL_TO_6
permissions = nil; or NSArray *permissions = [NSArray arrayWithObjects:#"email",nil];
#endif
NSLog(#"\npermissions = %#", permissions);
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:
^(FBSession *session,
FBSessionState state, NSError *error) {
NSLog(#"\nfb sdk error = %#", error);
switch (state) {
case FBSessionStateOpen:
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
//success
}
}];
break;
case FBSessionStateClosed:
//need to handle
break;
case FBSessionStateClosedLoginFailed:
//need to handle
break;
default:
break;
}
}];
}
I have the same problem on 3.1.3 FB SDK with iOS7.1. And I find a solution here. Hope it help!!
I have tried all answers here.
#loganathan nil permissions, #ill_always_be_a_warriors fbResync.
All of those don't work for me.
But I found it will works well when I launch the same code in iPhone 7.1 simulator
(without SSO"Single Sign On")
The same code works well on old version iOS FB SDK(not sure which version, but not 3.13)
(but no SSO will show when try to login)
So, I try to re-write a sample problem. I found several different here.
1. https://developers.facebook.com/docs/ios/getting-started Add new FacebookDisplayName
2. I modify my BundleID for iTune connect but I am not update it back to Faceboook App Dev
After modify those setting, it works on my iOS app with SSO feature.
Hope it help!!
Did you Try the RenewSystemCredential Methods? Take a look at this post:
Facebook iOS SDK extendAccessToken not Working - fbDidExtendToken not being called
I got the same error. But i used #ill_always_be_a_warriors method: -(void)fbResync but not work for me.
I finally found it's my permissions issue, i removed offline_access permission, it works, hope it helps some one.
In my application I need user to sign in to Facebook, get friend list in my table view and Post on feeds, but I don't want to redirect the user anywhere. so I used -openWithBehavior:completionHandler: ... Here is my code.
-(IBAction)loginAction:(id)sender {
[self deleteCookies];
// get the app delegate so that we can access the session property
DLAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
// this button's job is to flip-flop the session from open to closed
if (appDelegate.session.isOpen) {
// if a user logs out explicitly, we delete any cached token information, and next
// time they run the applicaiton they will be presented with log in UX again; most
// users will simply close the app or switch away, without logging out; this will
// cause the implicit cached-token login to occur on next launch of the application
[appDelegate.session closeAndClearTokenInformation];
} else {
if (appDelegate.session.state != FBSessionStateCreated) {
// Create a new, logged out session.
appDelegate.session = [[FBSession alloc] init];
[self updateView];
}
// if the session isn't open, let's open it now and present the login UX to the user
[appDelegate.session openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
// call the legacy session delegate
//Now the session is open do corresponding UI changes
{
FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];
[cacheDescriptor prefetchAndCacheForSession:session];
[FBSession openActiveSessionWithAllowLoginUI:NO];
[FBSession openActiveSessionWithPublishPermissions:[NSArray arrayWithObjects:#"publish_stream",#"publish_actions", nil] defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:NO completionHandler:nil];
}
break;
case FBSessionStateClosedLoginFailed:
{ // prefer to keep decls near to their use
// unpack the error code and reason in order to compute cancel bool
// call the legacy session delegate if needed
//[[delegate facebook] fbDialogNotLogin:userDidCancel];
}
break;
// presently extension, log-out and invalidation are being implemented in the Facebook class
default:
break; // so we do nothing in response to those state transitions
}
[self updateView];
}];
}
}
The user is successfully signed in and I can retrieve the friend list by using FQL. The problem is while posting to feeds. I know I need to get publish permissions to do it. But when I uses the following code to post...
- (IBAction)postAction:(id)sender {
DLAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
[FBSession openActiveSessionWithAllowLoginUI:NO];
NSMutableDictionary *postParams = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
#"https://developers.facebook.com/ios", #"link",
#"https://developers.facebook.com/attachment/iossdk_logo.png", #"picture",
#"Facebook SDK for iOS", #"name",
#"Build great social apps and get more installs.", #"caption",
#"The Facebook SDK for iOS makes it easier and faster to develop Facebook integrated iOS apps.", #"description",
nil];
if ([_postText.text length]>0) {
[postParams setObject:[_postText text] forKey:#"message"];
}
if (([FBSession.activeSession.permissions
indexOfObject:#"publish_actions"] == NSNotFound) ||
([FBSession.activeSession.permissions
indexOfObject:#"publish_stream"] == NSNotFound)) {
// No permissions found in session, ask for it
[FBSession.activeSession
reauthorizeWithPublishPermissions:
[NSArray arrayWithObjects:#"publish_stream",#"publish_actions",nil]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
// If permissions granted, publish the story
[self publishStory:postParams];
}
}];
} else {
// If permissions present, publish the story
[self publishStory:postParams];
}
}
}
-(void)publishStory:(NSDictionary *)postParams {
[FBRequestConnection startWithGraphPath:
#"me/feed" parameters:postParams HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
if (!error) {
//Tell the user that it worked.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Shared:"
message:[NSString stringWithFormat:#"Sucessfully posted to your wall."]
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
alertView.tag = 101;
[alertView show];
}
else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error:"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
NSLog(#"%#",error);
}
}
];
}
This code redirects the user to Safari or Facebook App. Which I don't want to happen.
Definitely I need to get publish permissions while logging in. the question is HOW?
You have to set FBSessionLoginBehavior, to change it the only way is to use:
[session openWithBehavior:FBSessionLoginBehaviorWithNoFallbackToWebView
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// Respond to session state changes,
// ex: updating the view
}];
I see you use FBSessionLoginBehaviorForcingWebView, so to get what you want you have to choose from this enum:
typedef enum {
/*! Attempt Facebook Login, ask user for credentials if necessary */
FBSessionLoginBehaviorWithFallbackToWebView = 0,
/*! Attempt Facebook Login, no direct request for credentials will be made */
FBSessionLoginBehaviorWithNoFallbackToWebView = 1,
/*! Only attempt WebView Login; ask user for credentials */
FBSessionLoginBehaviorForcingWebView = 2,
/*! Attempt Facebook Login, prefering system account and falling back to fast app switch if necessary */
FBSessionLoginBehaviorUseSystemAccountIfPresent = 3,
} FBSessionLoginBehavior;
Now to solve this "Definitely I need to get publish permissions while logging in. the question is HOW?" you may - (id)initWithPermissions:(NSArray*)permissions; your Session :
NSArray *permissions = #[#"publish_stream", #"publish_actions"];
appDelegate.session = [[FBSession alloc] initWithPermissions:permissions];
Have reviewed the facbook pages on how to integrate facebook with iOS, but what i had been looking for is a bit different.
I would like to prompt for Facbook login only when a user decides to share stuff, the flow explained in FB docs walk thru how to login (handle asyc response from FB login) and show publish button, but what we need is to show "Post to FB" button, when the user clicks, i would like the user to login and then go to the preview of what is going to be posted and then post to FB.
I am using FB SDK and iOS 5, the difficulty is how to wire FB login flow directly to Post flow.
Thanks
Elango
Below is some code that I wrote that does this. If the user has not signed in to Facebook from the device settings, it is a better user experience to just call openActiveSessionWithPublishPermissions:, which does both the read and publish permissions in one step. Otherwise, you just do the two permissions serially. As soon as the read permission succeeds, you do the publish permission.
I tested this code on an iOS6 and iOS5 device, using Facebook SDK 3.2.1
- (BOOL)hasFacebookInDeviceSettings
{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:#"com.apple.facebook"];
BOOL hasFacebookBuiltinAccount = (accountTypeFB != nil);
return hasFacebookBuiltinAccount;
}
- (BOOL)hasLoggedInToFacebookInDeviceSettings
{
if (![self hasFacebookInDeviceSettings]) {
return NO;
}
BOOL result = [SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook];
return result;
}
- (void)openFacebookSessionWithAllowLoginUI:(BOOL)allowLoginUI
{
if (![self hasLoggedInToFacebookInDeviceSettings]) {
// Simpler if we don't have the built in account
[FBSession openActiveSessionWithPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self facebookSessionStateChanged:session
state:state
error:error];
}];
}
else if (!FBSession.activeSession.isOpen) {
__block BOOL recursion = NO;
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
if (recursion) {
return;
}
recursion = YES;
if (error || !FBSession.activeSession.isOpen) {
[self facebookSessionStateChanged:session
state:state
error:error];
}
else {
assert(FBSession.activeSession.isOpen);
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
[FBSession.activeSession requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session,
NSError *error) {
[self facebookSessionStateChanged:session
state:FBSession.activeSession.state
error:error];
}];
}
}
}];
}
}
hasFacebookInDeviceSettings tells you if this device even supports Facebook from the settings (i.e. this is iOS6+).
hasLoggedInToFacebookInDeviceSettings tells you if the user has signed into to Facebook from the iOS6 Facebook device settings.
You'll need to create your own facebookSessionStateChanged: and other code, as described in the login tutorial