How to retrieve Email from Facebook SDK - ios

Note: please do not close as duplicate, I went through almost every existing thread here on Stackoverflow, but my problem is still not solved.
This is my Swift 3 function with the latest Facebook SDK:
let req = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"email,name"], tokenString: token?.tokenString, version: nil, httpMethod: "GET")
_ = req?.start(completionHandler: { (connection, result, error : Error?) -> Void in
if(error == nil) {
print("result \(result)")
} else {
print("error \(error!)")
}
})
Result:
result Optional({
id = 102080884567XXXXX;
name = "David Seek";
})
Email permission is approved:
Also the App is in live mode:
I have checked the reference guide, but I can't find my mistake.
My problem is, that I'm saving the facebookID as Email adress into my backend and I'm trying to figure out why... Therefore I have tried the provided code on top, but I'm not receiving the Email.
let result = FBSDKApplicationDelegate.sharedInstance().application(application,
open: url,
sourceApplication: sourceApplication,
annotation: annotation)
if result {
let token = FBSDKAccessToken.current()
let fieldsMapping = [
"id" : "facebookId",
"name" : "name",
"birthday": "birthday",
"first_name": "fb_first_name",
"last_name" : "fb_last_name",
"gender": "gender",
"email": "email"
]
backendless?.userService.login(withFacebookSDK: token, fieldsMapping: fieldsMapping, response: { (user: BackendlessUser?) in
}, error: { (fault: Fault?) -> Void in
print("Server reported an error: \(fault)")
})
}
I'm receiving every information, but the Email...
What am I missing? Help is very appreciated.

Email permission is granted:
That is not what that screenshot shows. It shows that it is approved, meaning your app can ask users for it. But it still has to ask.
Make sure that has happend successfully - either by debugging the access token, or via an API call to /me/permissions
You need to ask the user for permission during login.

Related

LISDKErrorAPIDomain error 403

I am trying to share a url, image and a text to linkedin through my app. But it shows an error as
The operation couldn’t be completed. (LISDKErrorAPIDomain error 403.)
My code is
func didLinkedinBtnPressed(cellObject: MyModel) {
let tmp = ["comment": cellObject.strSocialText!,
"content": ["title":"AppName", "description":cellObject.strSocialText!,"submitted-url":cellObject.strWebSite!,"submitted-image-url":cellObject.strImageUrl!],"visibility": ["code": "anyone"]] as [String : Any]
print("PostDtaa = \(tmp)")
let postData = try? JSONSerialization.data(withJSONObject: tmp, options: .prettyPrinted)
let url = NSString(string:"https://api.linkedin.com/v1/people/~/shares?format=json")
let permissions: [AnyObject] = [LISDK_BASIC_PROFILE_PERMISSION as AnyObject, LISDK_EMAILADDRESS_PERMISSION as AnyObject,LISDK_W_SHARE_PERMISSION as AnyObject]
LISDKSessionManager.createSession(withAuth: permissions, state: nil, showGoToAppStoreDialog: true, successBlock: { (success) -> () in
if LISDKSessionManager.hasValidSession() {
LISDKAPIHelper.sharedInstance().postRequest(url as String, body: postData, success: { (_ response) in
print(response ?? "")
self.simpleAlert(titleOfAlert: "Success", messageOfAlert: "Shared Successfully")
LISDKAPIHelper.sharedInstance().cancelCalls()
LISDKSessionManager.clearSession()
}, error: { (_errorRes) in
print(_errorRes?.localizedDescription ?? "No Error!!!")
LISDKAPIHelper.sharedInstance().cancelCalls()
LISDKSessionManager.clearSession()
})
}
}, errorBlock: { (error) -> () in
print("%s", "error called!")
LISDKAPIHelper.sharedInstance().cancelCalls()
LISDKSessionManager.clearSession()
})
}
Why am i getting a 403 error here?
I experimented a similar issue in the past it was related to the w_share permission
from the linkedin doc
Required permission: w_share
Whether set as a default permission in your app settings or requested
specifically via the scope argument during your authentication
process, you will need to request the w_share member permission in
order for your application to successfully make the API call to share
content.
w_share is disabled by default so it has to be explicitly enabled
NOTE: the token could be cached by app so in order to be sure that a new token (with the updated permissions) is used, I strongly suggest you to uninstall everything from your mobile device and re-install it again.

How to access user_location in Facebook Login?

I'm requesting the permissions like this:
fbLoginManager.logIn(withReadPermissions: ["public_profile", "email", "user_friends", "user_location"], from: self) { (result, error) in
Upon signup I can see it is asking me for the user_location:
let request = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"first_name, last_name, user_location"], httpMethod: "GET")
request?.start(completionHandler: { (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
print("Error: \(String(describing: error))")
}
else
{
print(result!)
}
let data:[String:AnyObject] = result as! [String : AnyObject]
})
But it seems the key is missing:
Error: Optional(Error Domain=com.facebook.sdk.core Code=8 "(null)" UserInfo={com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey=0, com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey=400, com.facebook.sdk:FBSDKErrorDeveloperMessageKey=(#100) Tried accessing nonexisting field (user_location) on node type (User), com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCode=100, com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey={
body = {
error = {
code = 100;
"fbtrace_id" = Hp3weSaqfI7;
message = "(#100) Tried accessing nonexisting field (user_location) on node type (User)";
type = OAuthException;
};
};
code = 400;
}})
fatal error: unexpectedly found nil while unwrapping an Optional value
But according to the docs, it should be on the user object. Thanks
But according to the docs, it should be on the user object.
No, it should not.
You are confusing the name of the permission - user_location - with the name of the actual field of the user object - location.
https://developers.facebook.com/docs/graph-api/reference/user/:
location
Page
The person's current location as entered by them on their profile. This field is not related to check-ins

backendless easy facebook login: fetching first name

I'm trying to login to facebook using backendless easyLogin* method in Swift and to fetch user's facebook name to display further. I'm able to login successfully but can't get the name.
The code is as the following ("first_name" is facebooks graph field to map, "displayName" is backendless custom user field):
let backendless = Backendless.sharedInstance();
backendless.userService.easyLoginWithFacebookFieldsMapping(
["email":"email", "first_name":"displayName"], permissions: ["email", "public_profile"],
response: {(result : NSNumber!) -> () in
print ("Result: \(result)")
},
error: { (fault : Fault!) -> () in
print("Server reported an error: \(fault)")
})
What am I missing here?
Not sure what was the exact problem but the following worked for me:
I've removed previously created facebook user from backendless user table
Tried to login using the following code snippet:
func easyFacebookLogin() {
let fieldsMapping = [
"name" : "name",
"first_name": "first_name",
"last_name" : "last_name",
"email": "email"]
backendless.userService.easyLoginWithFacebookFieldsMapping(
fieldsMapping,
permissions: ["email"],
response: {(result : NSNumber!) -> () in
print ("Result: \(result)")
},
error: { (fault : Fault!) -> () in
print("Server reported an error: \(fault)")
})
}
Everything worked as expected - name was fetched and mapped

Post on Facebook/ twitter in background in Swift

Can anyone recommend me any swift library to post on facebook and twiiter.
I am trying this for now
if FBSDKAccessToken.currentAccessToken().hasGranted("publish_actions")
{
print("publish actions already granted.")
}
else
{
FBSDKGraphRequest.init(graphPath: "me/feed", parameters: ["message" : "hello world"], HTTPMethod: "POST").startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error == nil))
{
print("Post id: \(result.valueForKey("id") as! String)")
}
})
}
There is a situation that when user creates an event then my app will automatically post/tweet on its wall about the event he just created.
I am fimiliar about swifter and Facebook SDK but i am not sure if it will help me post in background
How luschn said, you can't post automatically, but you can ask user if he want to post event.
For facebook post just use Facebook SDK(https://developers.facebook.com/docs/ios), you have there instruction for installation. You can use "Posting Data" from https://developers.facebook.com/docs/ios/graph, but you need first to check if user give you right to post it.
For Twitter post, apple give you a library(Social.framework) can help you for post on Twitter. You can learn how use it from http://code.tutsplus.com/tutorials/social-framework-fundamentals--mobile-14333. Also you can use this framework for facebook post.
guys i know i asked a silly question , but after upgrading my project to swift 2.0 and fb sdk 4.6 i did the posting
var params: NSDictionary = NSDictionary()
let userInfo: AnyObject = LocalStore.userDetails()!
let name = userInfo["name"] as? String
params = ["message": msgString]
let request: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/me/feed", parameters: params as [NSObject: AnyObject], HTTPMethod: "POST")
request.startWithCompletionHandler({ (connection, result, error) -> Void in })
This way you can post any message in background... but do check for fb login and ask for publishPermission(loginWithPublishPermission).

Facebook friends list api for swift ios

I have tried to get the facebook friends list for an IOS app, but receiving empty response from facebook.
How to get face book friends list in swift?
In Graph API v2.0 or above, calling /me/friends returns the person's friends who installed the same apps. Additionally, you must request the user_friends permission from each user. user_friends is no longer included by default in every login. Each user must grant the user_friends permission in order to appear in the response to /me/friends.
To get the list of friends who are using your app use following code:
let params = ["fields": "id, first_name, last_name, middle_name, name, email, picture"]
let request = FBSDKGraphRequest(graphPath: "me/friends", parameters: params)
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error != nil {
let errorMessage = error.localizedDescription
/* Handle error */
}
else if result.isKindOfClass(NSDictionary){
/* handle response */
}
}
If you want to access a list of non-app-using friends, then use following code:
let params = ["fields": "id, first_name, last_name, middle_name, name, email, picture"]
let request = FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: params)
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error != nil {
let errorMessage = error.localizedDescription
}
else if result.isKindOfClass(NSDictionary){
/* Handle response */
}
}
For fetching the friend list must allow user permission user_friends at the time of login.
For swift 3.0 add below code for fetching friend list:
let params = ["fields": "id, first_name, last_name, middle_name, name, email, picture"]
FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: params).start { (connection, result , error) -> Void in
if error != nil {
print(error!)
}
else {
print(result!)
//Do further work with response
}
}
I hope it works!
Remember only those friends are fetched who are using your app and u should have taken users read permission for user_friends while logging.
var fbRequest = FBSDKGraphRequest(graphPath:"/me/friends", parameters: nil);
fbRequest.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
println("Friends are : \(result)")
} else {
println("Error Getting Friends \(error)");
}
}
Refer to : https://developers.facebook.com/docs/graph-api/reference/v2.3/user/friends#read
Just making an union here that solved my problems:
From Dheeraj Singh, to get friends using your app:
var request = FBSDKGraphRequest(graphPath:"/me/friends", parameters: nil);
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
println("Friends are : \(result)")
} else {
println("Error Getting Friends \(error)");
}
}
And to get all facebook friends, from Meghs Dhameliya, ported to swift:
var request = FBSDKGraphRequest(graphPath:"/me/taggable_friends", parameters: nil);
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
println("Friends are : \(result)")
} else {
println("Error Getting Friends \(error)");
}
}
you can get friend list using taggable_friends
Graph API Reference for User Taggable Friend
/* make the API call */
[FBRequestConnection startWithGraphPath:#"/me/taggable_friends"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
/* handle the result */
}];
Swift - 4
This will only return your facebook friends using the same app.
// First you have to check that `user_friends` has associated with your `Access Token`, If you are getting false, please allow allow this field while you login through facebook.
if FBSDKAccessToken.current().hasGranted("user_friends") {
// Prepare your request
let request = FBSDKGraphRequest.init(graphPath: "me/friends", parameters: params, httpMethod: "GET")
// Make a call using request
let _ = request?.start(completionHandler: { (connection, result, error) in
print("Friends Result: \(String(describing: result))")
})
}
With user_friends permission you can have access to the list of your friends that also use your app, so if your app is not used by any of your friend, the list will be empty. See user_friends permission reference

Resources