I'm using ShareKit and have verified that the user is logged in to Facebook. I want to get their Facebook user name. Here's what I tried:
SHKFacebook *facebook = [[SHKFacebook alloc] init];
[facebook getAuthValueForKey:#"username"];
The getAuthValueForKey: method isn't returning anything to me. How can I get their Facebook user name?
You can use Facebook Graph API for get username. Add method bellow to FBSession.m class of FBConnect package.
#import "JSON.h"
...........
static NSString *const kGraphAPIURL = #"https://graph.facebook.com/";
static NSString *const kFBGraphAPIUserName = #"name";
...........
// Get user name via Facebook GraphAPI.
- (NSString *)getUserNameByUID:(FBUID)aUID {
NSString *userName_ = nil;
NSURL *serviceUrl = [NSURL URLWithString:[NSString stringWithFormat:#"%#%qi", kGraphAPIURL, aUID]];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSError *error = nil;
NSString *jsonString = [NSString stringWithContentsOfURL:serviceUrl encoding:NSUTF8StringEncoding error:&error];
if (error != nil) {
NSLog(#"######### error: %#", error);
}
if (jsonString) {
// Parse the JSON into an Object and
// serialize its object to NSDictionary
NSDictionary *resultDic = [jsonString JSONValue];
if (resultDic) {
userName_ = [resultDic valueForKey:kFBGraphAPIUserName];
}
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return userName_;
}
Related
How to do Facebook login in iOS without Facebook sdk(i am supporting iOS6 and iOS7).
My app is using Facebook login and user can share post on Facebook. Also i need to send the Facebook user id and auth token to my server.
Earlier I was supporting iOS 5 but now my iOS target >= iOS6 with Xcode 5.
For this i used Facebook SDK 3.11. From researching, i come to know that we can use SLComposeViewController, UIActivityViewController or SLRequest to share post. This will solve my sharing issue but how to do Facebook login and get auth token?
I tried SLRequest for Facebook login and SLComposeViewController for sharing, then is this good solution? (Here, i want to show Facebook native share dialog. So i haven't use SLRequest to share post because we have to make view for it.)
I referred this link. Is this the best solution to go forward?
only
-if you have deployment target 6
-you have set your bundle id in setting, develelopers.facebook.com
-you have set fb_app_id in your plist then
do like this without facebook sdk,
#import <Social/Social.h>
#import <Accounts/Accounts.h>
#define FB_APP_ID #"45666675444" // ur id here
#interface OGShareViewController ()
#property (strong, nonatomic) ACAccountStore *accountStore;
#property (strong, nonatomic) ACAccount *facebookAccount;
#property (strong, nonatomic) ACAccountType *facebookAccountType;
#end
-(void)viewDidLoad
{
[self getMyDetails];
}
- (void) getMyDetails {
if (! _accountStore) {
_accountStore = [[ACAccountStore alloc] init];
}
if (! _facebookAccountType) {
_facebookAccountType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
}
NSDictionary *options = #{ ACFacebookAppIdKey: FB_APP_ID };
[_accountStore requestAccessToAccountsWithType: _facebookAccountType
options: options
completion: ^(BOOL granted, NSError *error) {
if (granted) {
NSArray *accounts = [_accountStore accountsWithAccountType:_facebookAccountType];
_facebookAccount = [accounts lastObject];
NSURL *url = [NSURL URLWithString:#"https://graph.facebook.com/me"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:url
parameters:nil];
request.account = _facebookAccount;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableContainers
error:nil];
NSLog(#"id: %#", responseDictionary[#"id"]);
NSLog(#"first_name: %#", responseDictionary[#"first_name"]);
NSLog(#"last_name: %#", responseDictionary[#"last_name"]);
NSLog(#"gender: %#", responseDictionary[#"gender"]);
NSLog(#"city: %#", responseDictionary[#"location"][#"name"]);
NSLog(#"user name: %#", responseDictionary[#"username"]);
// http://graph.facebook.com/facebook/picture?type=normal
NSString *userPic = [NSString stringWithFormat:#" http://graph.facebook.com/%#/picture?type=normal", responseDictionary[#"username"]
];
NSLog(#"profile pic link: %#", userPic);
}];
} else {
[self showAlert:#"Facebook access for this app has been denied. Please edit Facebook permissions in Settings."];
}
}];
}
- (void) showAlert:(NSString*) msg {
dispatch_async(dispatch_get_main_queue(), ^(void) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"WARNING"
message:msg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
});
}
I want to code a singleton for facebook integration with iOS 6.
I use Social and Accounts Frameworks.
This my FacebookData.h :
#class FacebookData;
#protocol FacebookDataDelegate <NSObject>
#optional
- (void)FacebookDataDidLoadRequest:(NSDictionary *)result;
- (void)FacebookDataDidFailToLoadRequest:(NSError *)error;
#end
#interface FacebookData : NSObject{
NSString *facebookAppID;
ACAccountStore *facebookAccountStore;
ACAccountType *facebookAccountType;
ACAccount *facebookAccount;
BOOL readPermissionsGranted;
BOOL RequestPermissionsGranted;
}
#property (nonatomic) id delegate;
+ (FacebookData*)sharedFacebookData;
- (void)setAppID:(NSString *)appID;
- (NSString *)currentAppID;
- (void)requestPermissions:(NSArray*)Permissions andLoadRequest:(NSString*)theRequest;
- (void)loadRequest:(NSString*)theRequest;
#end
The most important methods of my FacebookData.m :
- (void)requestPermissions:(NSArray*)Permissions andLoadRequest:(NSString*)theRequest{
if(!readPermissionsGranted){
__block NSArray *facebookPermissions = #[#"read_stream", #"email"];
__block NSDictionary *facebookOptions = #{ ACFacebookAppIdKey : facebookAppID,
ACFacebookAudienceKey : ACFacebookAudienceFriends,
ACFacebookPermissionsKey : facebookPermissions};
[facebookAccountStore requestAccessToAccountsWithType:facebookAccountType options:facebookOptions completion:^(BOOL granted, NSError *error)
{
if (granted) {
readPermissionsGranted = YES;
[self requestPermissions:Permissions andLoadRequest:theRequest];
}
// If permission are not granted to read.
if (!granted)
{
NSLog(#"Read permission error: %#", [error localizedDescription]);
[self.delegate FacebookDataDidFailToLoadRequest:error];
readPermissionsGranted = NO;
if ([[error localizedDescription] isEqualToString:#"The operation couldn’t be completed. (com.apple.accounts error 6.)"])
{
[self performSelectorOnMainThread:#selector(showError) withObject:error waitUntilDone:NO];
}
}
}];
}else{
__block NSArray *facebookPermissions = [NSArray arrayWithArray:Permissions];
__block NSDictionary *facebookOptions = #{ ACFacebookAppIdKey : facebookAppID,
ACFacebookAudienceKey : ACFacebookAudienceFriends,
ACFacebookPermissionsKey : facebookPermissions};
[facebookAccountStore requestAccessToAccountsWithType:facebookAccountType options:facebookOptions completion:^(BOOL granted2, NSError *error)
{
if (granted2)
{
RequestPermissionsGranted = YES;
// Create the facebook account
facebookAccount = [[ACAccount alloc] initWithAccountType:facebookAccountType];
NSArray *arrayOfAccounts = [facebookAccountStore accountsWithAccountType:facebookAccountType];
facebookAccount = [arrayOfAccounts lastObject];
[self loadRequest:theRequest];
NSLog(#"Permission granted");
}
if (!granted2)
{
NSLog(#"Request permission error: %#", [error localizedDescription]);
[self.delegate FacebookDataDidFailToLoadRequest:error];
RequestPermissionsGranted = NO;
}
}];
}
}
- (void)loadRequest:(NSString*)theRequest{
__block NSDictionary *result= [[NSDictionary alloc]init];
// Create the URL to the end point
NSURL *theURL = [NSURL URLWithString:theRequest];
// Create the SLReqeust
SLRequest *slRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:theURL parameters:nil];
// Set the account
[slRequest setAccount:facebookAccount];
// Perform the request
[slRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (error)
{
// If there is an error we populate the error string with error
__block NSString *errorString = [NSString stringWithFormat:#"%#", [error localizedDescription]];
NSLog(#"Error: %#", errorString);
[self.delegate FacebookDataDidFailToLoadRequest:error];
} else
{
NSLog(#"HTTP Response: %i", [urlResponse statusCode]);
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
result = jsonResponse;
[self.delegate FacebookDataDidLoadRequest:jsonResponse];
}
}];
}
I use this singleton like this :
FacebookData *data = [FacebookData sharedFacebookData];
data.delegate = self;
[data setAppID:APPIDKEY];
[data requestPermissions:#[#"friends_location"] andLoadRequest:#"https://graph.facebook.com/me/friends?fields=id,name,location"];
This request with this permissions fails whereas the same method with permissions :#[#"email"] and request: https://graph.facebook.com/me/friends works perfectly.
This is the error that I can see in the console :
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
I can't find where the bug is, I don't know how to use tokens with these frameworks.
Thanks for your help !
IMO your LoadRequest URL is not correct
andLoadRequest:#"https://graph.facebook.com/me/friends?fields=id,name,location"];
SLRequest gives an oauth error even though its real problem with the URL. SLRequest doesn't support "?fields=id,name,location" directly in URL. You need to pass them as parameter in SLRequest
See the example below:
NSString* queryString = NULL;
queryString = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends", nil];
NSURL *friendsRequestURL = [NSURL URLWithString:queryString];
SLRequest *friendsRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET URL:friendsRequestURL
parameters:#{#"fields":#"id,name,location"}];
PS: I was facing the similar problem last night and cursing the facebook for given wrong error statement. But finally able to solve it at the end. :)
I'm working on 'deep linking' a Facebook request into my iOS app. A Facebook app is setup and seems to work as I can send a request to a friend, the request badge appears in the friend's Facebook, and clicking on the request launches my app (all on the iPhone).
However, so far I could not pass any data with the request, which I want to use when my app launched from the Facebook app with the request.
I use the following call:
-(void) fbRequestActionWithMessage: (NSString *) message andLink: (NSString *) link
{
NSDictionary *requestData = [NSDictionary dictionaryWithObjectsAndKeys:
#"data1", #"key1",
#"data2", #"key2",
nil];
NSString *requestDataString = [requestData JSONRepresentation];
NSMutableDictionary* params = [NSMutableDictionary
dictionaryWithObjectsAndKeys:
message, #"message",
#"Check this out", #"notification_text",
link, #"link",
requestDataString, #"data",
nil];
[facebook dialog:#"apprequests" andParams:params andDelegate:self];
}
Neither the "data" nor the "link" values in the params dictionary seem to have any effect. Ideally, when my app is launched from this request, I would get back the "data" or the "link" values. Can this be done?
I could not find any Facebook docs about the structure of params dictionary - is there a list of supported keys and their effect?
The "link" parameter and "notification_text" is not supported in iOS but you should be able to pass in data and get it back.
Example, passing in data:
FBSBJSON *jsonWriter = [FBSBJSON new];
NSDictionary *requestData = [NSDictionary dictionaryWithObjectsAndKeys:
#"data1", #"key1",
#"data2", #"key2",
nil];
NSString *requestDataString = [jsonWriter stringWithObject:requestData];
NSMutableDictionary* params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
message, #"message",
requestDataString, #"data",
nil];
[facebook dialog:#"apprequests"
andParams:params
andDelegate:self];
Example, reading it back:
....
#property (nonatomic, retain) NSURL *openedURL;
....
#synthesize openedURL = _openedURL;
....
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
self.openedURL = url;
return [FBSession.activeSession handleOpenURL:url];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[FBSession.activeSession handleDidBecomeActive];
if (FBSession.activeSession.isOpen) {
[self checkIncomingNotification];
}
}
- (void) notificationGet:(NSString *)requestid {
[FBRequestConnection startWithGraphPath:requestid
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (!error) {
NSString *title;
NSString *message;
if ([result objectForKey:#"data"]) {
// Process data in request
FBSBJSON *jsonParser = [FBSBJSON new];
NSDictionary *requestData =
[jsonParser
objectWithString:[result objectForKey:#"data"]];
[NSString stringWithFormat:#"Badge: %#, Karma: %#",
NSString *data1 = [requestData objectForKey:#"key1"];
NSString *data2 = [requestData objectForKey:#"key2"];
}
}
}];
}
- (void) checkIncomingNotification {
if (self.openedURL) {
NSString *query = [self.openedURL fragment];
if (!query) {
query = [self.openedURL query];
}
NSDictionary *params = [self parseURLParams:query];
// Check target URL exists
NSString *targetURLString = [params valueForKey:#"target_url"];
if (targetURLString) {
NSURL *targetURL = [NSURL URLWithString:targetURLString];
NSDictionary *targetParams = [self parseURLParams:[targetURL query]];
NSString *ref = [targetParams valueForKey:#"ref"];
// Check for the ref parameter to check if this is one of
// our incoming news feed link, otherwise it can be an
// an attribution link
if ([ref isEqualToString:#"notif"]) {
// Get the request id
NSString *requestIDParam = [targetParams
objectForKey:#"request_ids"];
NSArray *requestIDs = [requestIDParam
componentsSeparatedByString:#","];
// Get the request data from a Graph API call to the
// request id endpoint
[self notificationGet:[requestIDs objectAtIndex:0]];
}
}
// Clean out to avoid duplicate calls
self.openedURL = nil;
}
}
You can find more details on this, using the latest SDK v3.1:
https://developers.facebook.com/docs/howtos/send-requests-using-ios-sdk/
How to proceed after the Google Authentication in ios App? When i allow the access for my application. The window appear is "Please copy this code,switch to your application and copy it there:".I dont know how to proceed from here.
This is the code i write
SEL finishedSel = #selector(viewController:finishedWithAuth:error:);
viewController = [[GTMOAuth2ViewControllerTouch
controllerWithScope:scope
clientID:clientID
clientSecret:clientSecret
keychainItemName:nil
delegate:self finishedSelector:finishedSel]autorelease];
-(void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)auth
error:(NSError *)error {
if (error != nil) {
// Authentication failed
} else {
// Authentication succeeded
}
}
after getting the authentication
you can use it to get user data, see this code
NSString *urlStr = #"https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.auth authorizeRequest:request
completionHandler:^(NSError *error) {
NSString *output = nil;
if (error) {
output = [error description];
} else {
// Synchronous fetches like this are a really bad idea in Cocoa applications
//
// For a very easy async alternative, we could use GTMHTTPFetcher
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (data) {
// API fetch succeeded
output = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"output:%#",output);
} else {
// fetch failed
output = [error description];
}
}
}];
note you need to add this url in scope https://www.googleapis.com/auth/userinfo.profile
check this link gtm-oauth2
and here is a sample code of finishedWithAuth
(void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error {
if (error != nil) {
// Authentication failed (perhaps the user denied access, or closed the
// window before granting access)
NSLog(#"Authentication error: %#", error);
NSData *responseData = [[error userInfo] objectForKey:#"data"]; // kGTMHTTPFetcherStatusDataKey
if ([responseData length] > 0) {
// show the body of the server's authentication failure response
NSString *str = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"%#", str);
}
self.auth = nil;
} else {
// Authentication succeeded
//
// At this point, we either use the authentication object to explicitly
// authorize requests, like
//
// [auth authorizeRequest:myNSURLMutableRequest
// completionHandler:^(NSError *error) {
// if (error == nil) {
// // request here has been authorized
// }
// }];
//
// or store the authentication object into a fetcher or a Google API service
// object like
//
// [fetcher setAuthorizer:auth];
// save the authentication object
self.auth = auth;
}
}
I have an application which has been running happily, but since I updated to OS3.1 and updated the SDK the application is failing to log onto a remote server, passing a connection string to the stringWithContentsOfUrl function.
Before the update this was working fine, and if I copy the text string which is displayed on the NSLog statement and paste that into a browser, then I get the correct response, however, this is replying with "LOGIN_ERROR" indicating failure.
Any idea why this is now failing and how to fix it?
NSString* userName = [[NSUserDefaults standardUserDefaults] stringForKey:#"username_pref"];
NSString* password = [[NSUserDefaults standardUserDefaults] stringForKey:#"password_pref"];
NSString* loginUrl = [NSString stringWithFormat:#"https://website.com/API/login?email=%#&password=%#", userName, password];
NSLog (#"Logging in as %# using %# at [%#]", userName, password, loginUrl);
NSURL* url = [NSURL URLWithString:loginUrl];
NSString* loginDetails = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:nil];
if ([loginDetails compare:#"\"LOGIN_ERROR\""] == NSOrderedSame)
{
DLog (#"Login Failed : LOGIN_ERROR");
self.isLoggedIn = NO;
}
else
{
DLog (#"Login Success");
if (userDetails) {
[userDetails release];
}
NSDictionary* jsonData = [loginDetails JSONValue];
userDetails = [[[DMUserDetails alloc] init] retain];
userDetails.id = [[jsonData objectForKey:#"id"] intValue];
userDetails.api_token = [jsonData objectForKey:#"api_token"];
userDetails.full_name = [jsonData objectForKey:#"full_name"];
userDetails.mobile_number = [jsonData objectForKey:#"mobile_number"];
userDetails.mobile_host = [jsonData objectForKey:#"mobile_host"];
userDetails.email = [jsonData objectForKey:#"email"];
userDetails.twitter = [jsonData objectForKey:#"twitter"];
userDetails.jabber = [jsonData objectForKey:#"jabber"];
userDetails.msn = [jsonData objectForKey:#"msn"];
userDetails.start_page = [jsonData objectForKey:#"start_page"];
userDetails.date_format = [[jsonData objectForKey:#"date_format"] intValue];
userDetails.time_format = [[jsonData objectForKey:#"time_format"] intValue];
userDetails.sort_order = [[jsonData objectForKey:#"sort_order"] intValue];
userDetails.timezone = [jsonData objectForKey:#"timezone"];
userDetails.tz_offset = [jsonData objectForKey:#"tz_offset"];
userDetails.premium_until = [jsonData objectForKey:#"premium_until"];
userDetails.default_reminder = [jsonData objectForKey:#"default_reminder"];
self.isLoggedIn = YES;
}
[self performSelectorOnMainThread:#selector(didFinishLogon) withObject:nil waitUntilDone:NO];
If your user name is an e-mail address and has an at sign (#) in it, have you tried to escape the at sign in the URL by using %40 instead of #?
The most likely problem is that loginDetails is nil, indicating an error retrieving the URL, rather than you actually receiving a "LOGIN ERROR" response.
Pass in an error object and log the error.
Try:
NSError *error = nil;
NSString *loginDetails = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
if (error != nil) {
NSLog(#"%#", error);
}