FB Graph Subscription IOS send access_token - ios

There is something to the Facebook Graph SDK (and its iOS implementation) that really makes my life miserable. And it seems I'm on my own, because I don't seem to be able to find anyone on the 'net with a similar problem/lack of understanding like me.
Without further ado:
I have this code in my iOS app, that is supposed to subscribe my app to user updates:
-(void)subscribeToFacebook{
(FBSession.activeSession.isOpen) ? NSLog(#"is open") : NSLog(#"is closed");
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"page", #"object",
#"http://www.example.com/fbcallback.php", #"callback_url",
#"about, picture", #"fields",
#"ItsMeAlright", #"verify_token",
nil
];
/* make the API call */
[FBRequestConnection startWithGraphPath:#"/app/subscriptions"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
/* handle the result */
NSLog(#"error= %#",error);
}];
}
When I run this code, an error is logged, stating:
"(#15) This method must be called with an app access_token."
Now, I (think) I know how to get the access_token
NSString *fbAccessToken = [[[FBSession activeSession] accessTokenData] accessToken];
but I have't got a clue on where and when to send it to Facebook.
I tried to append it to the #"/app/subscriptions" part like this
NSString *urlString = [NSString
stringWithFormat:#"/app/subscriptions?access_token=%#",
[fbAccessToken stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
but that didn't work.
Your input is extremely welcome!

The way to do this will be to create a FBSession with the application token. Because the current session isn't what you want.
https://developers.facebook.com/docs/reference/ios/current/class/FBSessionTokenCachingStrategy
https://developers.facebook.com/docs/facebook-login/ios#sessions
But, security wise, you shouldn't be doing this at all. It's very insecure to embed your application token in a production application. I believe that the iOS sample generated for you is incorrect.
You should be sending any request that requires the application token with a server call (e.g. PHP)

Related

IOS: what is native "Facebook Login SDK for iOS"?

I am working on ios application where I have to implement facebook publish/share feature. what I have done for sharing is
1: if user is not logged in, I am checking with this
if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded||FBSession.activeSession.state == FBSessionStateOpen) {
//NSLog(#"Open");
//Set already opened session to FBSession
[FBSession setActiveSession:appDelegate.session];
//if user logged in already, perform sharing on fb
[self sharePostOnFb];
}else{
//if user is not logged in
[self openFbLogin];
}
-(void)openFbLogin
{
[FBSession openActiveSessionWithReadPermissions:#[#"public_profile", #"email",#"publish_actions"] allowLoginUI:YES completionHandler:^(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];
if (state == FBSessionStateOpen) {
NSLog(#"opened");
[self sharePostOnFb];
}
}];
}
-(void)sharePostOnFb
{
NSString *strBznsName = [[[Global sharedInstance]getBznsInfo] objectForKey:#"name"];
NSString *strUserReceive = [NSString stringWithFormat:#"%# %# received %#.",[[[Global sharedInstance]getUserData] objectForKey:#"firstname"],[[[Global sharedInstance]getUserData] objectForKey:#"lastname"],dataStampDeal.strDealTerms];
NSString *urlLogoBkString= #URL_BZNSImgPath;
NSURL *urlLogoBkImage = [NSURL URLWithString:[NSString stringWithFormat:#"%#/%#",urlLogoBkString,[[[Global sharedInstance]getBznsInfo] objectForKey:#"logo" ]]];
NSString *StrUrl = [NSString stringWithFormat:#"%#",urlLogoBkImage];
// Put together the dialog parameters
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
strBznsName, #"name",
#"Powered By Anyloyalty", #"caption",
strUserReceive, #"description",
StrUrl, #"picture",
nil];
// Make the request
[FBRequestConnection startWithGraphPath:#"/me/feed"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
// Link posted successfully to Facebook
NSLog(#"result: %#", result);
strFbPostId = [result valueForKey:#"id"];
NSLog(#"post id: %#", strFbPostId);
//[self WebServiceHandler:NO];
//[appDelegate startanimation];
} else {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
NSLog(#"%#", error.description );
NSDictionary *errorInformation = [[[[error userInfo] objectForKey:#"com.facebook.sdk:ParsedJSONResponseKey"]
objectForKey:#"body"]
objectForKey:#"error"];
//NSLog(#"%#", errorInformation );
//__block NSString *alertText = #"Your action will not be published to Facebook.";
__block NSString *alertText = [errorInformation valueForKey:#"message"];
[[[UIAlertView alloc] initWithTitle:#"error"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil] show];
}
}];
}
facebook login (-(void)openFbLogin()) is opening web dialog. After successfully logged in. I am sharing post ( -(void)sharePostOnFb()) on fb and I am getting error
"(#200) The user hasn't authorized the application to perform this action"
For publishing/sharing I have to get approval for "publish_actions" permission from FB. I have submitted my application to FB app developer center. I am getting this message.
"Your app must not use a Facebook Web Dialog. Utilize our native Facebook Login SDK for iOS, so that users do not need to login twice."
so Now I want to "what is native Facebook Login SDK for iOS"? and how can I integrate that with my app?
The native Facebook login is nothing but using the iOS FB framework and create login using that. It is clearly mentioned on the developers.facebook.com how to login using there framework. You can also see the samples provided by them for login.
What this actually does is that , it check if the user has a Facebook application installed in the device and is user logged in to the Facebook app. If user is already logged in then user won't be asked to log in again. If user isn't logged in then they will be redirected to safari where they will have to log in to FB.
Its quite simple to integrate. Its well explained.
Facebook clearly says,
All iOS and Android apps should use their SDK's for iOS and Android for requesting permissions. Other apps should use their JavaScript for requesting permissions wherever possible.
Native applications on iOS and Android especially should use their SDK flows as they are optimized and work robustly across various types of devices without any manual adjustment.
In particular, their native SDKs let people who are already logged in to their Facebook app grant permissions without having to log in to their Facebook accounts again. This will result in far better conversion than not using our SDK and rendering our login dialogs inside web views embedded within your native app since the web view will not have any Facebook session data initially and will require people to login to their Facebook account.
Please note: if you are using Apple's Social framework, you may continue to do so, but ensure that if the user is not using the iOS integration, that your app falls back to the Facebook SDK for iOS. This can create more work than necessary, though, so we highly recommend using their SDK instead.
Here are the SDK implementation details:Facebook Login SDK for iOS

Facebook Like Button - canĀ“t build archive with the new feature FBLikeControl

I want to integrate Facebook like Button with the new feature FBLikeControl. On the facebook page they have written it is only for developement and not for publication on the AppStore.
Here is the Tutorial from facebook https://developers.facebook.com/docs/ios/like-button/
When I want to build an archive with my code I get the error message "Use of undeclared identifier FBBetaFeaturesLikeButton".
Is there a way to solve this problem or if there's any other alternative solution, I would appreciate that.
Here is my code:
[FBSettings enableBetaFeature:FBBetaFeaturesLikeButton];
[FBSettings enablePlatformCompatibility:NO];
FBLikeControl *like = [[FBLikeControl alloc] init];
like.frame = CGRectMake((self.frame.size.width-like.frame.size.width)/2, facebookY, 60, 20);
like.objectID = #"https://www.facebook.com/pages/abcdefgh/123456789?ref=tn_tnmn";
[self addSubview: like];
This link says:
FBLikeControl is a preview feature and may not be deployed to the App
Store. Only developers and testers of your Facebook app will be able
to use the Like Button.
is the reason you are unable to built the archive.
There are several ways to implement like, the one which worked for me is as follows:
[FBRequestConnection startWithGraphPath:#"/object-id_to_like/likes"
parameters:nil
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
// Handle error here
}];
Here is the Link
EDIT: It is pretty simple, you just have to replace FBLikeControl code in your project with the above method call replacing object-id_to_like to the actual post-id/ object-id. What the method does is it POSTS a like on corresponding object/post.
In case you have problem to fetch the object id of the object/post you can fetch it using same method with the HTTPMethod parameter set to #"GET". Following code will return posts from your timeline:
[FBRequestConnection startWithGraphPath:#"/me/home"// you can change this to #"/me/feed" if required
parameters:nil
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error ) {
if (!error){
// Fetch Post-id/Object-id here
}else{
// handle error here
}
}];

How to Like in Facebook using FacebookSDK.framework Facebook

I have used FacebookSDK.framework for Facebook integration in my application. I have to like one facebook page from application. I have used following code for liking page.
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:#"https://www.facebook.com/demoappname"
, #"object",
nil
];
/* make the API call */
[FBRequestConnection startWithGraphPath:#"me/og.likes"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
)
{
NSDictionary *currentResult= [(NSArray *)[result data] objectAtIndex:0];
if(!error)
{
NSLog(#"there is no error");
}
else
{
NSLog(#"There is something wrong at here.");
}
}];
But I am not clear what I have to pass in "object" parameter. Can anybody help to what I am doing wrong at here.
Thanks,
If you read this documentation, it says-
The og.likes action can refer to any open graph object or URL, except for Facebook Pages or Photos.
So, liking a page with Graph API isn't possible.
The only thing you can do- add a Like Button to the page in your app.

Google Places API Autocomplete on iOS

Over the last few days I've been struggling to get Google Places autocomplete to work on my app, and no matter what I do, I always get the REQUEST_DENIED error.
I followed Google's "tutorial" for the implementation, Places API is enabled, API key has the correct bundle ID, I also tested with a Browser ID, with no success.
I am pretty sure it has something to do with the key, though. Curiously, on the Android version of the app, the service will work with the Browser Key. And on the browser, obviously, it works with that key too.
These are the two keys I experimented with:
And this is my implementation code, using AFNetworking:
NSURL *url = [NSURL URLWithString:#"https://maps.googleapis.com/maps/api/place/autocomplete/"];
NSDictionary *params = #{#"input" : [input stringByReplacingOccurrencesOfString:#" " withString:#"+"],
#"location" : [NSString stringWithFormat:#"%f,%f", searchCoordinate.latitude, searchCoordinate.longitude],
#"sensor" : #(true),
// #"language" : #"pt_BR",
// #"types" : #"(regions)",
// #"components" : #"components=country:br",
#"key" : GOOGLE_API_KEY};
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient setParameterEncoding:AFFormURLParameterEncoding];
[httpClient getPath:#"json"
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *JSON = [[NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil] dictionaryWithoutNulls];
if (completion) {
completion(JSON[#"predictions"]);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *errorResponse) {
NSLog(#"[HTTPClient Error]: %# for URL %#", [errorResponse localizedDescription], [[[operation request] URL] path]);
}];
I know there are some questions like this one here, but some are old, and say that Places API does not work on Android or iOS, which clearly is not the case anymore, since Google itself publishes examples on both platforms, as seen on Places API page: https://developers.google.com/places/documentation/autocomplete
A workaround I'm currently using is Apple's GeoCoding system, which works good when you type the full address, but is terrible with half-typed phrases. This is not good at all, I'd really like to use Google's API.
I got it!
The paramenter sensor should receive either #"true"or #"false", and not #(true)or #(false).
For the record, the API key used is indeed the Browser Key, and not an iOS key.
You should init httpClient with base URL #"https://maps.googleapis.com/" and get path /maps/api/place/autocomplete/json. Base URL - host only, it does not take other parts of path, so in your case you get request to URL "https://maps.googleapis.com/json".
https://maps.googleapis.com/maps/api/geocode/json?address="%#","%#"&sensor=false,yourAddress,your c

ObjC, Facebook Page - posting news feed works, but posting photo does not

so I'm trying to post a photo on my Facebook page (I'm admin) from iPhone app. I'm using FB Sessions to create the session, get the read permission, get manage_pages permission, then, I successfully get my Facebook Pages app-ids as a result of
[FBRequestConnection startWithGraphPath:#"/me/accounts" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
NSLog(#"%#", [result description]);
}]; // have token, what now?
Which is still fine. Then, I try to post a photo to the app_id/photos feed, and it does not work = it uploads the photo correctly, but shows me (as in my profile) uploading the photo rather then the Page itself. What could be the problem?
Here's the code for the params and the call
NSDictionary *params = [NSDictionary
dictionaryWithObjects: [NSArray arrayWithObjects:
[UIImage imageNamed:#"Icon.png"],
#"This is my first photo post from xcode app", nil]
forKeys:[NSArray arrayWithObjects:
#"source",
#"message", nil]];
[FBRequestConnection startWithGraphPath:#"MyPageID/photos" parameters:params HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
NSLog(#"%#", [result description]);
} ];
the [result description] log from the call is fine (it returns the id = xx and "post_id" = yy, which I assume are correct), as is the call itself - the only problem is that it shows me as the author, and not the Page itself.
MyPageID is correct, because calling
NSDictionary *paramsFeed = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"This is my first page post from xcode app", nil] forKeys:[NSArray arrayWithObjects:#"message", nil]];
[FBRequestConnection startWithGraphPath:#"390106241058188/feed" parameters:paramsFeed HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
NSLog(#"result: %#", [result description]);
}];
Also, calling me/photos and posting the photo there with dictionaryKey #"picture" works, and it posts the photo on my own wall perfectly.
Do anyone knows where the problem could be hidden?
I found the solution, although I find it weird that I did not have to do this for the /feed page update
Huge thanks goes for Mr. Arpit Kumar Kulshrestha, who pointed out the right way in my previous incarnation of the problem ( Xcode - how to share photo from iPhone app to Facebook managed page feed )
the solution:
I've tried setting a new FBSession before, but it still had a lot of errors in it, so I've left that route and went to another one. However, it makes perfect sense to do that -
create FBAccessTokenData, which has the Page's token in it, and set other things to the same as the active session - like this
FBAccessTokenData *tokenData = [FBAccessTokenData createTokenFromString:pageTokenString permissions:[FBSession activeSession].accessTokenData.permissions expirationDate:[FBSession activeSession].accessTokenData.expirationDate loginType:FBSessionLoginTypeFacebookApplication refreshDate:nil];
then, one need to create a new FBSession, and what is important, it needs to have set its tokenCacheStrategy to something without data, i.e.[FBSessionTokenCachingStrategy nullCacheInstance] . I did a blank allocation ([[FBSession alloc] init]), and that gave me a lot of errors, however when I use this one
FBSession *sessionFb = [[FBSession alloc] initWithAppID:appID permissions:[NSArray arrayWithObjects: #"publish_stream", #"manage_pages", nil] urlSchemeSuffix:nil tokenCacheStrategy:[FBSessionTokenCachingStrategy nullCacheInstance]];
it works perfectly. And when you have this new session, you want to open the path for the data to come and go, and you can make it like this:
[sessionFb openFromAccessTokenData:tokenData completionHandler:^(FBSession *session, FBSessionState status, NSError *error)
{
}];
and the last part before it starts working correctly is setting the activeSession to this newly allocated and opened session, this way:
[FBSession setActiveSession:sessionFb];
after I've made all of these changes, the photo page sharing started to work magically.
However, I'm still not sure how is it possible that the photo share did not work before but the feed share did.. but this solves my issue.

Resources