iOS FBSDKShare API shareWithContent fails to post - ios

I'm trying to use the Facebook iOS Sharing SDK 4.1 but not getting a post off. I have an active session, but the following code does not post to my feed, and I do not get any of the callbacks either (success, error, or cancel), even though the caller is a FBSDKSharingDelegate. I have attempted to emulate the sample code in the SDK documentation but to no avail.
if ( [[FBSDKAccessToken currentAccessToken] hasGranted:#"publish_actions"] ) {
FBSDKShareLinkContent* content = [[FBSDKShareLinkContent alloc] init];
content.contentURL = _Object.myPostServerURL;
content.contentDescription = _Object.myPostDescription;
content.contentTitle = #"New Post";
content.imageURL = _Object.coverArtServerURL;
BOOL ok = [[FBSDKShareAPI shareWithContent:content delegate:self] share];
}
I've tried with and without the "share" message wrapped around the shareWithContent; I can't tell from the documentation if it is required. Either way, no callbacks to delegate, no post. Can someone help me?

FBSDKShareLinkContent *tempContent=[[FBSDKShareLinkContent alloc] init];
tempContent.contentTitle=#"hello";
tempContent.contentDescription=#"desc";
tempContent.imageURL=[NSURL URLWithString:#"https://camo.githubusercontent.com/67212912f8d2d6a474d1af756603f7c13c837112/687474703a2f2f692e696d6775722e636f6d2f375976386d53412e676966"];
tempContent.contentURL=[NSURL URLWithString:#"https://scrumptious-facebook.parseapp.com/meals/italian/?fb_action_ids=10200411040395078&fb_action_types=fb_sample_scrumps%3Aeat"];
_shareAPI.delegate = self;
_shareAPI.shareContent = tempContent;
[_shareAPI share];
Also to use FBSDKShareAPI,You have to implement your for login and request for necessary permissions through u get FBSDKAccessToken,then only u can directly post to user feed.This is according to documentation of Facebook,If u want to show your own interface of sharing.
Currently may be your delgate may not work but might be ur app may face the issues of no access tokens and no permission issues
[[[FBSDKLoginManager alloc] init]
logInWithPublishPermissions:#[publish_actions]
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if ([result.grantedPermissions containsObject:publish_actions]) {
[_shareAPI share];
} else {
// This would be a nice place to tell the user why publishing
// is valuable.
}
}];
//Delegate methods
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results{
}
- (void)sharerDidCancel:(id<FBSDKSharing>)sharer{
}
- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error{
NSLog(#"%#",error);
}

You have to make some configuration in your appdelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];}
and
- (void)applicationDidBecomeActive:(UIApplication *)application {
[FBSDKAppEvents activateApp];
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.}

Related

Can we add or use handleOpenURL other app delegate

I'm building SDK for my product and there will be no app delegate class. I used Dropbox Integration in my SDK, so I'm bound to use following method.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSString *stringUrl = [url absoluteString];
if ([stringUrl containsString:#"cancel"]) {
// Handle if user cancelled the login
[[NSNotificationCenter defaultCenter] postNotificationName:#"dropboxRegistrationCancel" object:self];
return NO;
}
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
[[NSNotificationCenter defaultCenter] postNotificationName:ApplicationComeBackFromDropBoxLoginPage object:self];
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
So Issue is there is no app delegate than how can use above method?
Or any alternate solution for this to use this in another class (like to inherit UIResponder class).
Looking for help.
If you are building a SDK with no appDelegate, then well, you have nothing to do. It will be in your project where you will be using your sdk that you will have to add this line.
By the way, the line NSString *stringUrl = [url absoluteString]; is absolutly useless since you are not using stringUrl later on, and the
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// NSString *stringUrl = [url absoluteString];
return YES;
}
just means: yes you can quit my app to open another app when the user click on a link.
No biggy....

iOS: Facebook SDK AppInvite error 9

For some reason I keep getting an error for the AppInvite Dialog...
After setting up the info.plist for iOS9 by the documentation, setting all Facebook's parameters on the project, I get the error method being called with: Error Domain=com.facebook.sdk.core Code=9 "(null)".
App link was made on Facebook's Hosting API.
- (void) appInviteDialog:(FBSDKAppInviteDialog *)appInviteDialog didFailWithError:(NSError *)error{
NSLog(#"error: %#",error);
}
the method I use to invoke the dialog:
-(void)inviteFriends{
FBSDKAppInviteDialog* dia= [[FBSDKAppInviteDialog alloc] init];
if ([dia canShow])
{
FBSDKAppInviteContent *content =[[FBSDKAppInviteContent alloc] init];
content.appLinkURL = [NSURL URLWithString:self.applink];
content.appInvitePreviewImageURL = [NSURL URLWithString:self.preview_image];
[FBSDKAppInviteDialog showFromViewController:self.rootViewController.mainViewController withContent:content delegate:self];
}
[dia release];
return;
}
I tried calling inviteFriends in different places, but it won't start and would get to the didFailWithError method.
However, for some reason it may start working all of a sudden, and would work all the time ever since, unless the app is deleted from the device and reinstalled. In this case, it won't open again...
Make sure you have [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions]; in your AppDelegate. I've spend two days while trying to fix that.
Also make sure you have [FBSDKAppEvents activateApp];
in applicationDidBecomeActive:(UIApplication *)application

FBSDKSharingDelegate callback not working, even when post works fine

FBSDKSharingDelegate callback is not working. I can post to facebook fine with the ios SDK, but I'd like to detect if the post was successful and take additional action to notify the user. However, the callback is not working for me. The delegate methods are not being called and I don't know why.
Using ios8, Parse as my backend. In Parse, the user is linked to FB. I'm using the IOS simulator.
What I've tried:
I've ensured that publish permissions are granted, saved, and linked to the Parse user. I've run a check and "publish_actions" are detected OK. The posting works fine as I can see the post on the facebook account. It's just the callback that is not working. I've checked my fb setup and it looks fine. For good measure at the very bottom I've included that relevant code from my app delegate. I've blocked out confidential keys with XXXX.
Code:
1st: See if user is logged in to Parse, if not, send to sign in and link to facebook account. Once that is done, I request "publish" permissions and link that additional permission to the Parse user. I know this works b/c when I recompile, it remembers the "publish" permissions and goes right to into the post.
#interface FacebookAPIPost () <FBSDKSharingDelegate>
#end
#implementation FacebookAPIPost
-(void)shareSegmentFacebookAPI { //if statement below
//1) logged in?, if not send to sign up screen
//2) else if logged in, link account to facebook account, then send post
//3) else send to post b/c signed up and linked already.
PFUser *currentUser = [PFUser currentUser];
if(!currentUser) {
[self pushToSignIn];
} else if(![PFFacebookUtils isLinkedWithUser:currentUser]){
[self linkUserToFacebook:currentUser];
NSLog(#"user account not linked to facebook");
} else {
[self shareSegmentWithFacebookComposer];
}
}
-(void)linkUserToFacebook:currentUser{
[PFFacebookUtils linkUserInBackground:currentUser withPublishPermissions:#[#"publish_actions"] block:^(BOOL succeeded, NSError *error) {
if(error){
NSLog(#"There was an issue linking your facebook account. Please try again.");
}
else {
NSLog(#"facebook account is linked");
//Send the facebook status update
[self shareSegmentWithFacebookComposer];
}
}];
}
-(void)shareSegmentWithFacebookComposer{
if ([[FBSDKAccessToken currentAccessToken] hasGranted:#"publish_actions"]) {
[self publishFBPost]; //publish
} else {
NSLog(#"no publish permissions"); // no publish permissions so get them, then post
[PFFacebookUtils linkUserInBackground:[PFUser currentUser]
withPublishPermissions:#[ #"publish_actions"]
block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"User now has read and publish permissions!");
[self publishFBPost];
}
}];
Here is where the post gets made:
-(void) publishFBPost{
FBSDKShareLinkContent *content = [FBSDKShareLinkContent new];
content.contentURL = [NSURL URLWithString:[self.selectedSegment valueForKey:#"linkToContent"]];
content.contentTitle = [self.selectedProgram valueForKey:#"programTitle"];
content.contentDescription = [self.selectedSegment valueForKey:#"purposeSummary"];
PFFile *theImage = [self.selectedSegment valueForKey:#"segmentImage"];
NSString *urlString = theImage.url;
NSURL *url = [NSURL URLWithString:urlString];
content.imageURL = url;
FBSDKShareDialog *shareDialog = [FBSDKShareDialog new];
[shareDialog setMode:FBSDKShareDialogModeAutomatic];
// [FBSDKShareDialog showFromViewController:self.messageTableViewController withContent:content delegate:self];
[shareDialog setShareContent:content];
[shareDialog setDelegate:self];
[shareDialog setFromViewController:self.messageTableViewController];
[shareDialog show];
}
Delegate methods below are not working. Meaning after the post is complete, I can see it on the FB account, but none of these delegate methods execute.
#pragma mark - delegate methods
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results {
// if ([sharer isEqual:self.shareDialog]) {
NSLog(#"I'm going to go crazy if this doesn't work.%#",results);
// Your delegate code
// }
}
- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error
{
NSLog(#"sharing error:%#", error);
NSString *message = error.userInfo[FBSDKErrorLocalizedDescriptionKey] ?:
#"There was a problem sharing, please try again later.";
NSString *title = error.userInfo[FBSDKErrorLocalizedTitleKey] ?: #"Oops!";
[[[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
- (void)sharerDidCancel:(id<FBSDKSharing>)sharer
{
NSLog(#"share cancelled");
}
Console output:
The only message I get back after posting is after a few seconds this message appears:
plugin com.apple.share.Facebook.post invalidated
Please help!
Footnote: appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize Parse.
[Parse enableLocalDatastore];
[Parse setApplicationId:#"XXXX"
clientKey:#"XXX"];
[PFFacebookUtils initializeFacebookWithApplicationLaunchOptions:launchOptions];
//Initialize Facebook
[FBSDKAppEvents activateApp];
return [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
}
//Method added for facebook integration
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[FBSDKAppEvents activateApp];
}
I think I am too late answering this question but someone else could trap into this as well, that's why sharing my knowledge.
As per Facebook API documentation
sharer:didCompleteWithResults: Sent to the delegate when the share completes without error or cancellation.
The results from the sharer. This may be nil or empty.
its probably because this delegate method is only get called when the post is successfully shared. In case of failure the other delegate method sharer:didFailWithError:get called. I think Facebook API should not need to add the result parameter is that case.
So in my experience if sharer:didCompleteWithResults whenever this is called that would mean success.

Facebook login crashes on cold starts

I have a little trouble when implementing new Facebook Login for our app. We are using Facebook SDK v4.3 for our development. And the login/signup process crashes on devices with low memory. We suspect that the low memory constraints have caused our app to terminate when it triggered a switch to Facebook for authentication. As document in the Facebook's old SDK (link https://developers.facebook.com/docs/facebook-login/ios#login-apicalls):
Login flows require an app switch to complete, it's possible your app gets terminated by iOS in low memory conditions or if your app does not support backgrounding.
In that case, the state change handler supplied to your open call disappears.
To handle that scenario explicitly assign a state change handler block to the FBSession instance any time prior to the handleOpenURL: call:
// During the Facebook login, your app passes control to the Facebook iOS app or Facebook in a mobile browser.
// After authentication, your app will be called back with the session information.
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
// Note this handler block should be the exact same as the handler passed to any open calls.
[FBSession.activeSession setStateChangeHandler:^(FBSession *session, FBSessionState state, NSError *error) {
// Retrieve the app delegate
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
// Call the app delegate's sessionStateChanged:state:error method to handle session state changes
[appDelegate sessionStateChanged:session state:state error:error];
}];
return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
}
Unfortunately, the new Facebook SDK deprecated FBSession.activeSession and its stateChangeHandler. I followed the custom UI FBLogin button for my app, here is my appDelegate code
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
return [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
The code works fine and executes perfectly under normal condition. However, it behave oddly under cold starts (due to low memory). So my question would be: How do we prevent this? Is there an equivalent handler for the new SDK?
PS. I did my job in managing the device's memory. But it still didn't work under this stressed conditions.
Edit: All I want is to grab the user's basic information on success. Therefore, I did not need keep track (or have the need to) of the access token. This is the block of code that I use to invoke login
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login logInWithReadPermissions:#[#"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
[ErrorMessageDisplay displayErrorAlertOnViewController:self withTitle:FB_LOGIN_ERROR_TITLE andMessage:FB_LOGIN_ERROR_MESSAGE];
[self.loginView enableLoginButtons];
} else if (result.isCancelled) {
[ErrorMessageDisplay displayErrorAlertOnViewController:self withTitle:FB_LOGIN_CANCEL_TITLE andMessage:FB_LOGIN_CANCEL_MESSAGE];
[self.loginView enableLoginButtons];
} else {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:nil] startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id user, NSError *error) {
//TODO do something in here
}];
}
}];
Using the part of the code, the app still freeze on low memory after authenticated using facebook. In fact, the handler did not get call at all
Make sure you follow all the steps in https://developers.facebook.com/docs/ios/getting-started including connecting the application:didFinishLaunchingWithOptions: of the FBSDKApplicationDelegate (in addition to the openURL:)
Check FBSDKAccessToken currentAccessToken in an appropriate area of your app (such as viewDidLoad, as described in https://developers.facebook.com/docs/facebook-login/ios/). This will be set for you by the SDK in cases of a "cold start" of your app.

Facebook Integration and data fetching not working

I have used the following code to fetch data from the Facebook to my app.
I have did all the other stuff in app delegate and plist.
This sometimes works and fetched data and sometimes don't. Can anyone help me with this. I can't figure what the problem is!
- (IBAction)facebook:(id)sender
{
FBLoginView *loginView=[[FBLoginView alloc]init];
loginView.delegate=self;
loginView.readPermissions = #[#"first_name",
#"last_name",
#"location",
#"id",
#"access_token"];
NSArray* permissions = [NSArray arrayWithObjects: #"email", nil];
loginView.readPermissions=permissions;
[FBSession openActiveSessionWithAllowLoginUI:YES];
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
id<FBGraphUser> user1,
NSError *error) {
if (!error) {
firstname=user1.first_name;
lastname=user1.last_name;
city=[user1.location objectForKey:#"name"];
email=user1[#"email"];
fbid=user1.id;
Loggedin=#"Y";
[[NSUserDefaults standardUserDefaults]setObject:Loggedin forKey:#"token"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
if (![fbid isEqualToString:#""])
{
[self performSegueWithIdentifier: #"Facebooksegue" sender: self];
}
NSLog(#"%#",firstname);
NSLog(#"%#",lastname);
NSLog(#"%#",city);
NSLog(#"%#",email);
NSLog(#"%#",fbid);
}];
}
My AppDelegate
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBSession class];
return YES;
}
I had a similar situation and I had used almost the same code as you did.
My problem was with the test Facebook id which I had used. I hadn't had it verified so it didn't respond with the email. Try using another account and it might work. If not check whether your app is authorized with the Facebook account synchronized with your account in the settings.
Hope this helps.
Go to the blue project icon at the top left, select your target, go to build settings, find other linker flags, add -ObjC. This will make it so that the entire framework gets statically linked and thus you can reference FBLoginView in the storyboard successfully.

Resources