Trying to implement Facebook iOS SDK on my iphone App. I am using FBDialog Delegate to allow the user to login and get the response/callback using the delegate.
I would like to grab the code in response_type from the user once the login is successful.
Can anyone help me out here or let me know where to take the guide from.
I have the following code which is implemented :
-(void) login{
self.fb = [[Facebook alloc] initWithAppId:AppID andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
self.fb.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
self.fb.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
fb.sessionDelegate = self;
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:AppID forKey:#"client_id"];
[params setObject:#"code" forKey:#"response_type"];
[fb dialog:#"oauth" andParams:params andDelegate:self];
NSLog(#"Callback: %#", params);
}
In didReceiveResponse, the delegate method called when response is beginning (not yet complete and parsed), get the statusCode from the response object.
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
if (200 == [response statusCode]) {
NSLog(#"Success");
}
}
Just handle the delegate methods:
/**
* Your application should implement this delegate to receive session callbacks.
*/
#protocol FBSessionDelegate <NSObject>
#optional
/**
* Called when the user successfully logged in.
*/
- (void)fbDidLogin;
/**
* Called when the user dismissed the dialog without logging in.
*/
- (void)fbDidNotLogin:(BOOL)cancelled;
/**
* Called when the user logged out.
*/
- (void)fbDidLogout;
#end
Related
I'm trying to figure out what this error means...
I'm trying to get user information via Facebook sdk. All I need is their email and name
Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0xde94ad0 {error=<CFBasicHash 0xde7d100 [0x3f616650]>{type = mutable dict, count = 3,
entries =>
2 : <CFString 0xde722a0 [0x3f616650]>{contents = "type"} = <CFString 0xdeba1a0 [0x3f616650]>{contents = "OAuthException"}
3 : <CFString 0xde6ba20 [0x3f616650]>{contents = "message"} = <CFString 0xdeb12a0 [0x3f616650]>{contents = "An active access token must be used to query information about the current user."}
6 : <CFString 0xde74c40 [0x3f616650]>{contents = "code"} = 2500
}
}
My basic code... (below in my viewDidLoad)
facebook = [[Facebook alloc] initWithAppId:#"random#123456" andDelegate:self];
[self login];
(below in my login method)
- (void) login {
NSArray *permissionsArray = [NSArray arrayWithObjects:#"email", nil];
[facebook authorize:permissionsArray];
}
(and my Facebook request methods...)
- (void)request:(FBRequest *)request didLoad:(id)result {
NSLog(#"Inside didLoad");
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
// When we ask for user infor this will happen.
if ([result isKindOfClass:[NSDictionary class]]){
//NSDictionary *hash = result;
NSLog(#"Name: %#", [result objectForKey:#"name"]);
}
if ([result isKindOfClass:[NSData class]])
{
NSLog(#"Profile Picture");
//[profilePicture release];
//profilePicture = [[UIImage alloc] initWithData: result];
}
NSLog(#"request returns %#",result);
//if ([result objectForKey:#"owner"]) {}
};
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error{
NSLog(#"%#",error);
}
I'm really confused to why I get an error and what I need to change or add in order to fix it...
Any ideas?
EDIT: My request code:::
- (IBAction)requestFBFriends:(id)sender {
NSLog(#"HERE");
[facebook requestWithGraphPath:#"me/friends" andDelegate:self];
}
Here's how you can get the name and email...
I didn't test it so if it doesn't work just tell and I'll find out the problem.
The method that sends the request needs to authenticate if you don't have a valid access token
-(void)getUserFBInfo
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
self.facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
self.facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![self.facebook isSessionValid]) {
NSLog(#"auth");
[self.facebook authorize:[NSArray arrayWithObject:#"email"]];
} else {
[self apiFQLIMe];
}
}
#pragma mark -
#pragma mark FBSessionDelegate
/**
* Called when the user successfully logged in.
*/
- (void)fbDidLogin
{
[self reportAction:#"FB allowed"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[self.facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[self.facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[self apiFQLIMe];
}
/**
* Called when the user dismissed the dialog without logging in.
*/
- (void)fbDidNotLogin:(BOOL)cancelled
{
NSLog("did not login");
}
/**
* Called after the access token was extended. If your application has any
* references to the previous access token (for example, if your application
* stores the previous access token in persistent storage), your application
* should overwrite the old access token with the new one in this method.
* See extendAccessToken for more details.
*/
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt
{
NSLog(#"token extended");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:accessToken forKey:#"FBAccessTokenKey"];
[defaults setObject:expiresAt forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
/**
* Called when the user logged out.
*/
- (void)fbDidLogout
{
NSLog("did logout")
}
/**
* Called when the current session has expired. This might happen when:
* - the access token expired
* - the app has been disabled
* - the user revoked the app's permissions
* - the user changed his or her password
*/
- (void)fbSessionInvalidated
{
[self.facebook authorize:[NSArray arrayWithObject:#"email"]];
}
#pragma mark -
#pragma mark FBRequestDelegate
- (void)apiFQLIMe {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"SELECT name, first_name, middle_name, last_name, username, contact_email FROM user WHERE uid=me()", #"query",
nil];
[self.facebook requestWithMethodName:#"fql.query"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
}
/**
* Called when the Facebook API request has returned a response.
*
* This callback gives you access to the raw response. It's called before
* (void)request:(FBRequest *)request didLoad:(id)result,
* which is passed the parsed response object.
*/
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response
{
DLog(#"received response");
}
/**
* Called when a request returns and its response has been parsed into
* an object.
*
* The resulting object may be a dictionary, an array or a string, depending
* on the format of the API response. If you need access to the raw response,
* use:
*
* (void)request:(FBRequest *)request
* didReceiveResponse:(NSURLResponse *)response
*/
- (void)request:(FBRequest *)request didLoad:(id)result
{
NSLog(#"%#",result);
// check the log to know how you receive the result
}
/**
* Called when an error prevents the Facebook API request from completing
* successfully.
*/
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error
{
NSLog(#"Err message: %#", [[error userInfo] objectForKey:#"error_msg"]);
NSLog(#"Err code: %d", [error code]);
}
If you have questions ask them in the comments
If you are running the application on Simulator/device Try cleaning the build and fresh install the application. The current error might be due to inactive/revoked access token which is no longer valid to access user data.
Hope it helps!!!
I have recently added Facebook integration to my app, and everything works fine except when the user relaunches the app. Each time the app is restarted, Facebook has to go back through its authorization process. This involves switching out of the app to Safari/Facebook, then back to my app. How can I make Facebook save the info, or be able to get blanket permissions for my app so that I doesn't constantly reauthorize?
Here is my code from the applicationDidFinishLaunchingWithOptions: method:
facebook = [[Facebook alloc] initWithAppId:#"203604286395694" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
Relevant Facebook delegate methods:
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (void) requestDialogButtonClicked {
NSMutableDictionary* params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"invites you to check out cool stuff", #"message",
#"Check this out", #"notification_text",
nil];
[facebook dialog:#"apprequests"
andParams:params
andDelegate:self];
}
- (void)dialogDidComplete:(FBDialog *)dialog {
NSLog(#"dialog completed successfully");
}
Are you calling Facebook authorize: somewhere? That's how the fbDidLogin will be triggered. Assuming you are, the behavior indicates that either the token or the date (or both) is nil, or that the date is past expiration (unlikely).
Log the values upon writing and reading the user defaults. My guess is that the authorize either wasn't called, or failed (due to app key or some other problem not shown in the code), leaving the fbDidLogin method uncalled or saving nil values.
That's because you are not asking for permissions when you authorize your app .. "offline_access" provide a long term access token so you will not need to get a new access token every time the user wants to use the Facebook .. so what you need to authorize your app like this
if (![facebook isSessionValid]) {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_likes",
#"read_stream",
#"offline_access"
nil];
[facebook authorize:permissions];
[permissions release];
}
Edit :
Please check the following in your implementation :
1.you need to add the following functions in your application delegate(the Facebook object here is your instance value of FaceBook Class).
// Pre 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
return [facebook handleOpenURL:url];
}
// For 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
2.In your info.plist add to URL types > URL Schemes > your Facebook app ID with fb prefix (finally your value will be like this for ex. fb313714***).
I am making an application where I need to invoke requests in multiple view controllers. I don't want the Facebook log in screen to show when the app is launched. It should only open when the user taps a button in another view controller if the user is not logged in, so putting the code in app delegate is not working solution to the problem. And the whole asynchronous process of requesting data in the Facebook API is killing me, I am starting to loose hair.
A class with static methods to get the facebook object and treat it as a singleton.
#import "PBSocialMedia.h"
#import "PBFacebookDelegate.h"
static Facebook *facebook;
static PBFacebookDelegate *facebookDelegate;
#implementation PBSocialMedia
+ (Facebook *)sharedFacebook {
if (facebook == nil) {
facebookDelegate = [[PBFacebookDelegate alloc] init];
facebook = [[Facebook alloc] initWithAppId:#"156687441079334" andDelegate:facebookDelegate];
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
NSArray *permissions = [NSArray arrayWithObjects:#"user_photo_video_tags", #"friends_photo_video_tags", #"user_photos", #"friends_photos", nil];
if (![facebook isSessionValid]) {
[facebook authorize:permissions];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:#"connectedToFacebook" object:self];
}
return facebook;
}
+ (Facebook *)sharedFacebookWithoutAuthorizing {
return facebook;
}
#end
A class that implements the Facebook session delegate used in the class above
#import "PBFacebookDelegate.h"
#import "PBSocialMedia.h"
#implementation PBFacebookDelegate
/**
* Called when the user successfully logged in.
*/
- (void)fbDidLogin {
Facebook *facebook = [PBSocialMedia sharedFacebook];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:#"connectedToFacebook" object:self];
}
/**
* Called when the user dismissed the dialog without logging in.
*/
- (void)fbDidNotLogin:(BOOL)cancelled {
[[NSNotificationCenter defaultCenter] postNotificationName:#"dismissedFacebookDialog" object:self];
}
/**
* Called when the user logged out.
*/
- (void)fbDidLogout {
[[NSNotificationCenter defaultCenter] postNotificationName:#"disconnectedFromFacebook" object:self];
}
#end
As you see from the two classes above I am making use of notifications so that I know when the user logs in/out of Facebook. The code below is an example of how I am trying to use it:
- (void)viewDidLoad {
[super viewDidLoad];
Facebook *facebook = [PBSocialMedia sharedFacebook];
if (self.canUseGraphAPI) {
[facebook requestWithGraphPath:#"106378916135129/photos" andDelegate:self];
NSLog(#"Can use");
} else {
NSLog(#"Can't use");
}
}
- (void)connectedToFacebook {
self.canUseGraphAPI = YES;
}
- (void)disconnectedFromFacebook {
self.canUseGraphAPI = NO;
}
This is ofcourse NOT working as intended because of the stupid asynchronous request. It will work correct only when the user is logged in. So the first time I open the app it invokes the [PBSocialMedia sharedFacebook]; Then it proceed with the request function AND NOT waiting for the sharedFacebook function to finish. I really hope somebody has encountered this problem before. I want to do requests in different places in my code, but only when the user is logged in, and it need to WAIT while the user logs in before requesting. The code below is not working but it shows what I want!
- (void)viewDidLoad {
[super viewDidLoad];
Facebook *facebook = [PBSocialMedia sharedFacebook];
while (self.canUseGraphAPI) {
// WAITING FOR LOGIN IN
}
[facebook requestWithGraphPath:#"106378916135129/photos" andDelegate:self];
}
- (void)connectedToFacebook {
self.canUseGraphAPI = YES;
}
- (void)disconnectedFromFacebook {
self.canUseGraphAPI = NO;
}
I would start restructuring your code to work by passing in blocks that you want executed upon getting your answer back from FB. This is similar to how you do ajax in JQuery.
- (void)viewDidLoad {
[super viewDidLoad];
Facebook *facebook = [PBSocialMedia sharedFacebook];
[self withGraphAPIDo: ^{
[facebook requestWithGraphPath:#"106378916135129/photos" andDelegate:self];
}];
}
I just went through the "Getting Started > Mobile Apps" documentation on Facebook developers. They provided the code to ask permission for accessing information but they don't specify where that code is suppose to go.
Could you tell me where to put the code? Because I don't want to put it in the wrong space.
The code I want to add:
NSArray* permissions = [[NSArray arrayWithObjects:
#"publish_stream", #"offline_access", nil] retain];
[facebook authorize:permissions delegate:self];
My appDelegate code:
#import "iOSTestAppDelegate.h"
#implementation iOSTestAppDelegate
#synthesize facebook;
#synthesize viewController=_ViewController;
#synthesize window=_window;
#synthesize managedObjectContext=__managedObjectContext;
#synthesize managedObjectModel=__managedObjectModel;
#synthesize persistentStoreCoordinator=__persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
/* Step 2. Within the body of the application:didFinishLaunchingWithOptions: method create instance of the Facebook class using your app id */
facebook = [[Facebook alloc] initWithAppId:#"********"];
/* Step 3. Once the instance is created, check for previously saved access token information. */
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
/* Step 4. Check for a valid session and if it is not valid call the authorize method which will both signin the user and prompt the user to authorize the app: */
if (![facebook isSessionValid]) {
[facebook authorize:nil delegate:self];
}
return YES;
}
/* Step 5. Add the application:handleOpenURL: method to the AppDelegate with a call to the facebook instance: */
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
/* Step 6. Implement the fbDidLogin method from the FBSessionDelegate implementation. In this method you will save the user's credentials specifically the access token and corresponding expiration date. */
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
...
#end
After allocate your facebook instance, you have to provide these permission for authorizing the facebook from the user_credentials. it means were getting these permission from the user who are login.
facebook=[[Facebook alloc]initWithAppId:kAppId];
_permissions = [[NSArray arrayWithObjects:#"publish_stream",#"offline_access",nil]retain];
[facebook authorize:_permissions delegate:self];
Publish stream provides : Enables your app to post content, comments, and likes to a user's stream and to the streams of the user's friends. With this permission, you can publish content to a user's feed at any time, without requiring offline_access. However, please note that Facebook recommends a user-initiated sharing model.
Offline Access:
Enables your app to perform authorized requests on behalf of the user at any time. By default, most access tokens expire after a short time period to ensure applications only make requests on behalf of the user when the are actively using the application. This permission makes the access token returned by our OAuth endpoint long-lived.
Refer more details about permission here
iOS beginner here. I'm using the following code to save my facebook accessToken and expirationDate in NSUserDefaults:
facebook = [[Facebook alloc] initWithAppId:#"225083222506272"];
[facebook authorize:nil delegate:self];
NSString *access=[facebook accessToken];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:access, #"accessToken",[facebook expirationDate], #"expirationDate",nil];
[defaults registerDefaults:appDefaults];
And I'm trying to retrieve accessToken and expirationDate in a later call with:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *access=[defaults valueForKey:#"accessToken"];
NSDate *date=[defaults objectForKey:#"expirationDate"];
[facebook fbDialogLogin:access expirationDate:date];
but access and date are null. What am I doing wrong?
The code here is not synchronous. It means it does not block after the call to [facebook authorize:nil delegate:self];. You should instead implement the fbDidLogin delegate method to be notified of when the user has actually logged in successfully. At that point, retrieve the access tokens and save them to user defaults.
Here's a partial sample:
- (void)userClickedFacebookLogin {
[facebook authorize:nil delegate:self]; // delegate is self
}
// Delegate method that you should implement to get notified
// when user actualy logs in.
- (void)fbDidLogin {
// now get the access token and save to user defaults
NSString *access = [facebook accessToken];
// ..
}
Also make sure that the class which has the above code implements the FBSessionDelegate protocol at minimum.
#interface MyClass <FBSessionDelegate> {
}
#end
Look at the DemoApp sample and specifically the DemoAppViewController class from Facebook to get a better idea.