FBNativeDialogNotSupported Facebook sdk 3.1 - objective-c

With the release of Facebook SDK 3.1 it has a class which launches the Facebook Native Dialog for Post in iOS 6.
Below is the code for it.
[FBNativeDialogs presentShareDialogModallyFrom:currentController initialText:nil image:nil url:nil handler:^(FBNativeDialogResult result, NSError *error) {
//Print Error
}];
Error Domain=com.facebook.sdk Code=7 "The operation couldn’t be completed. (com.facebook.sdk error 7.)" UserInfo=0x1e5e0930 {com.facebook.sdk:NativeDialogReasonKey=com.facebook.sdk:NativeDialogNotSupported
So, I tried to login first using the following code and then launch the FBNativeDialog. But, it does not enter the completion handler, when Okay button is pressed of Facebook permission window in Safari.
AppDelegate *appDelegate=[[UIApplication sharedApplication] delegate];
appDelegate.session = [[FBSession alloc] initWithPermissions:[NSArray arrayWithObjects:#"publish_stream", nil]];
[appDelegate.session openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
[FBNativeDialogs presentShareDialogModallyFrom:currentController initialText:nil image:nil url:nil handler:^(FBNativeDialogResult result, NSError *error) {
NSLog(#"Dialog Error= %#",error);
}];
break;
default:
break;
}
}];

when Okay button is pressed of Facebook permission window in Safari
You need to set up the Facebook account on the iOS 6 device/simulator in order to use the native share dialogs. Once you have done so, you will get native iOS permissions dialogs as well so there should be no app switching to Safari to login. See my similar response to http://facebook.stackoverflow.com/a/12681352/1712979

Related

iOS Facebook integration shows 'App Not Setup' error

I am having Facebook login in my iOS App. After following all the steps from developer.facebook.com and successful integration I can see a button in my view on clicking that button it redirects to safari and asking for fb username and password but after logging in it shows 'App Not Setup' error. Here I have 3 questions
I want everything to load inside the app itself
I don't want the FB login button, I want to load the FB page on viewdidload/appear
Whats the reason for "App not Setup" error. I want to test with successful loginenter
There might be various reasons for "App not setup" like
Check your plist file where you are entering 'FacebookAppID' and URL string
a)check your facebook app id
b)check your URL String facebook app id has prefix 'fb'
c)Check your bundle id i.e com.yourapp.com is properly set on facebook app settings or not.
d) Check you have entered all correct information in app settings of your facebook app.
If you don't strictly need to use Facebook SDK you could use the Social.framework. That way you wouldn't have to worry about the bundle id or Facebook App ID.
Here's a sample code to show how it works:
SLComposeViewController *slComposeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[slComposeViewController setInitialText:MyText];
[slComposeViewController setTitle:MyTitle];
if (![slComposeViewController addURL:url]) {
NSLog(#"Unable to add url");
}
[self presentViewController:slComposeViewController animated:YES completion:nil];
//Check the result
slComposeViewController.completionHandler = ^(SLComposeViewControllerResult result)
{
switch (result) {
case SLComposeViewControllerResultCancelled:
//Do something
break;
case SLComposeViewControllerResultDone:
//Do something
break;
}
};
//If iOS < 7.0 dismiss the viewcontroller
NSString *version = [[UIDevice currentDevice] systemVersion];
if ([version floatValue] < 7.0)
{
dispatch_async(dispatch_get_main_queue(), ^{
[slComposeViewController dismissViewControllerAnimated:NO completion:^{
// Do something
}];
});
}

iOS facebook SDK: Login already authenticated

I have had the Facebook iOS SDK running in an app I've been working on for a few months. At this point I am mostly using the SDK for SSO purposes.
Since I have started using iOS 6.0 I have been seeing an issue where the "Login to use your FB account with MY_APP" modal is blocking my current view.
The odd thing is that the user is already authenticated and apparently authorized to use my app. This is proven by the fact that I can get the user's email address and such.
It is also important to note that if I click the "X" it will close and everything is fine (user is authenticated/authorized). If I login as it tells me, it shows the "MY_APP is already authorized" modal which I cannot click the "Okay" button but I can click the "X" which again drops me back into my view with the user authenticated and authorized.
Here you can see the it:
To authenticate I am calling the following method in the appdelegate:
[appDelegate openSessionWithAllowLoginUI:YES];
The following are the relevant FB methods in my appdelegate:
// FACEBOOK STUFF
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [NSArray arrayWithObjects: #"email", nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
}
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState)state
error:(NSError *)error {
// FBSample logic
// Any time the session is closed, we want to display the login controller (the user
// cannot use the application unless they are logged in to Facebook). When the session
// is opened successfully, hide the login controller and show the main UI.
switch (state) {
case FBSessionStateOpen: {
FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];
[cacheDescriptor prefetchAndCacheForSession:session];
[self sendAuthenticationStatusChangedNotification];
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
// FBSample logic
// Once the user has logged in, we want them to be looking at the root view.
[FBSession.activeSession closeAndClearTokenInformation];
//[self showLoginView];
break;
default:
break;
}
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// FBSample logic
// We need to handle URLs by passing them to FBSession in order for SSO authentication
// to work.
return [FBSession.activeSession handleOpenURL:url];
}
EDIT 1
I noticed that this is happing on one of my phones but not the other. The phone that wasn't working had an older version of the FB app installed. Updating the FB app stopped this issue from happening. I am still interested in a fix to avoid others from experiencing the same issue.
EDIT 2
The issue went away for a little but now is back even with the new facebook app installed. Please help!
The problem for me actually turned out to be a silly one. I was calling
[appDelegate openSessionWithAllowLoginUI:YES];
two times due to a button click event that was wired up twice. As soon as it was only being called once, the issue went away!

Ask permission to access Camera Roll

I have a settings view where the user can choose switch on or off the feature 'Export to Camera Roll'
When the user switches it on for the first time (and not when he takes the first picture), I would like the app to ask him the permission to access the camera roll.
I've seen behavior in many app but can't find the way to do it.
I'm not sure if there is some build in method for this, but an easy way would be to use ALAssetsLibrary to pull some meaningless bit of information from the photo library when you turn the feature on. Then you can simply nullify what ever info you pulled, and you will have prompted the user for access to their photos.
The following code for example does nothing more than get the number of photos in the camera roll, but will be enough to trigger the permission prompt.
#import <AssetsLibrary/AssetsLibrary.h>
ALAssetsLibrary *lib = [[ALAssetsLibrary alloc] init];
[lib enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
NSLog(#"%zd", [group numberOfAssets]);
} failureBlock:^(NSError *error) {
if (error.code == ALAssetsLibraryAccessUserDeniedError) {
NSLog(#"user denied access, code: %zd", error.code);
} else {
NSLog(#"Other error code: %zd", error.code);
}
}];
EDIT: Just stumbled across this, below is how you can check the authorization status of your applications access to photo albums.
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
if (status != ALAuthorizationStatusAuthorized) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Attention" message:#"Please give this app permission to access your photo library in your settings app!" delegate:nil cancelButtonTitle:#"Close" otherButtonTitles:nil, nil];
[alert show];
}
Since iOS 8 with Photos framework use:
Swift 3.0:
PHPhotoLibrary.requestAuthorization { status in
switch status {
case .authorized:
<#your code#>
case .restricted:
<#your code#>
case .denied:
<#your code#>
default:
// place for .notDetermined - in this callback status is already determined so should never get here
break
}
}
Objective-C:
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
switch (status) {
case PHAuthorizationStatusAuthorized:
<#your code#>
break;
case PHAuthorizationStatusRestricted:
<#your code#>
break;
case PHAuthorizationStatusDenied:
<#your code#>
break;
default:
break;
}
}];
Important note from documentation:
This method always returns immediately. If the user has previously granted or denied photo library access permission, it executes the handler block when called; otherwise, it displays an alert and executes the block only after the user has responded to the alert.
Since iOS 10, we also need to provide the photo library usage description in the info.plist file, which I described there. And then just use this code to make alert appear every time we need:
- (void)requestAuthorizationWithRedirectionToSettings {
dispatch_async(dispatch_get_main_queue(), ^{
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusAuthorized)
{
//We have permission. Do whatever is needed
}
else
{
//No permission. Trying to normally request it
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status != PHAuthorizationStatusAuthorized)
{
//User don't give us permission. Showing alert with redirection to settings
//Getting description string from info.plist file
NSString *accessDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSPhotoLibraryUsageDescription"];
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:accessDescription message:#"To give permissions tap on 'Change Settings' button" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:cancelAction];
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:#"Change Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}];
[alertController addAction:settingsAction];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
}
}];
}
});
}
Also, there are some common cases when the alert doesn't appear. To avoid copying I would like you to take a look at this answer.
The first time the user tries to write to camera roll on ios 6 he/she is automatically asked for permission. You don't have to add extra code (before that the authorisationstatus is ALAuthorizationStatusNotDetermined ).
If the user denies the first time you cannot ask again (as far as I know). The user has to manually change that app specific setting in the settings->privacy-> photos section.
There is one other option and that is that it the user cannot give permission due other restrictions like parental control, in that case the status is ALAuthorizationStatusRestricted
Swift:
import AssetsLibrary
var status:ALAuthorizationStatus = ALAssetsLibrary.authorizationStatus()
if status != ALAuthorizationStatus.Authorized{
println("User has not given authorization for the camera roll")
}
#import <AssetsLibrary/AssetsLibrary.h>
//////
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusRestricted:
{
//Tell user access to the photos are restricted
}
break;
case ALAuthorizationStatusDenied:
{
// Tell user access has previously been denied
}
break;
case ALAuthorizationStatusNotDetermined:
case ALAuthorizationStatusAuthorized:
// Try to show image picker
myPicker = [[UIImagePickerController alloc] init];
myPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
myPicker.delegate = self;
[self presentViewController: myPicker animated:YES completion:NULL];
break;
default:
break;
}
iOS 9.2.1, Xcode 7.2.1, ARC enabled
'ALAuthorizationStatus' is deprecated: first deprecated in iOS 9.0 -
Use PHAuthorizationStatus in the Photos framework instead
Please see this post for an updated solution:
Determine if the access to photo library is set or not - PHPhotoLibrary (iOS 8)
Key notes:
Most likely you are designing for iOS7.0+ as of todays date, because of this fact you will need to handle both ALAuthorizationStatus and PHAuthorizationStatus.
The easiest is to do...
if ([PHPhotoLibrary class])
{
//Use the Photos framework
}
else
{
//Use the Asset Library framework
}
You will need to decide which media collection you want to use as your source, this is dictated by the device that your app. will run on and which version of OS it is using.
You might want to direct the user to settings if the authorization is denied by user.

Facebook sdk: ActiveSession is still closed after I give permission

I am integrating facebook login in my application. I jsut want the user to be able to login and I get his birthday and Location.
I got the latest Facebook SDK and successfully added it to my application. I also created a new application on facebook and added the key provided to my application.
I have created a button "Login with facebook" and done the following
When the user clicks the button
// handler for button click
- (IBAction)facebookLoginTouched:(id)sender {
[self openSessionWithAllowLoginUI:YES];
}
This method will show the user the facebook login page in order to get his permission
-(BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_location",
#"user_birthday",
nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self HandleLogin];
}];
}
Then if login and permission successful
- (void)HandleLogin {
if (FBSession.activeSession.isOpen) {
//THIS IS NEVER REACHED
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
id<FBGraphUser> user,
NSError *error) {
//DO SOMETHING WITH THE USER INFO
}];
}
}
My problem:
When I click on the button the facebook page comes in correctly and I enter my username/password. It logged me correctly and I gave permission for the application to access my information. When I finish, I return to the app successfully.
However when the code reaches FBSession.activeSession.isOpen it returns false.
Why is the session still closed after I correctly logged in and gave permission?
Any help is greatly appreciated.
Thanks
You may be missing code to process the return from the Facebook app. Add the following in your app delegate implementation file:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBSession.activeSession handleOpenURL:url];
}

Post status update to Facebook from iOS application

I am creating an iOS application and I am adding some sharing options. I already downloaded the Facebook 3.0 SDK and placed it in my project in accordance with the Facebook developer page. All I need my application to do is post text-only status updates to Facebook when a certain button is clicked on an UIActionSheet. Here is the code I have so far:
#import <FacebookSDK/FacebookSDK.h>
-(void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
NSArray *permissions = [NSArray arrayWithObject:#"publish_actions"];
[FBSession openActiveSessionWithPermissions:permissions allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// session might now be open.
if (session.isOpen)
//don't know what to do from here
}];
}
}
I don't know where to proceed from here. The authentication takes place and then the Facebook app on my iPhone opens and that is the end of it. Also, if there is anything else I should add that I am missing PLEASE let me know. I am new to Facebook SDK.
Facebook's iOS documentation covers this very nicely in their sample application and tutorials.
Specifically
HelloFacebookSample: combines use of FBLoginView,
FBProfilePictureView, FBFriendsPickerViewController,
FBPlacePickerViewController, and FBRequest for profile access, status
updates and photo uploading.
From developer.facebook.com