Not getting the email from twitter using Fabric Twitter SDK - objective-c

This seems to be age old question with no specific answers or solutions for it. I had my application whitelisted from twitter. Done all the things. Checked the request email from user box and used the following code
[[Twitter sharedInstance] startWithConsumerKey:#"FabricKey" consumerSecret:#"FabricSecretKey"];
if ([[Twitter sharedInstance] session]) {
TWTRShareEmailViewController *shareEmailViewController =
[[TWTRShareEmailViewController alloc]
initWithCompletion:^(NSString *email, NSError *error) {
NSLog(#"Email %# | Error: %#", email, error);
}];
[self presentViewController:shareEmailViewController
animated:YES
completion:nil];
But still it is returning null. Why is this?? I even created the application in twitter developer portal. Please help me. Is twitter trying to be more over secure?? It is just pissing me out......

Related

OSX ACAccountStore requestAccessToAccountsWithType... returning 'granted=No' and error=nil after denying permissions

I am trying to request access to my facebook account. The first time I ran this it went well and I saw the popup requesting permissions. The popup asked me to allow or deny. I chose to deny because I wanted to test that use case. Now I cannot figure out how to get it to allow access again. I have deleted the app from my facebook account and deleted my facebook account from my mac. I've also tried adding the property
#"auth_type": #"rerequest"
to the options dictionary. I get the same result no matter what.
As mentioned in the title, the error is nil and granted is False.
Thanks in advance.
ACAccountType* accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary* options = #{
ACFacebookAppIdKey: [[NSBundle mainBundle] objectForInfoDictionaryKey:#"FacebookAppID"],
ACFacebookPermissionsKey: #[#"public_profile", #"email", #"user_friends"],
};
[accountStore requestAccessToAccountsWithType:accountType options:options completion:^(BOOL granted, NSError* error)
{
if (granted)
{
ACAccount* account = [[accountStore accountsWithAccountType:accountType] lastObject];
macFacebookAccount = account;
}
else
{
NSLog(#"%#", error);
}
}];
I solved this: Facebook permission settings for an app are located under System Preferences > Security and Privacy. From there just click facebook and check the box next to your app

How to do login in Twitter using STTwitter for OSX?

Hello,
I am developing a Twitter client for OSX using STTwitter library.
I use this code to do login:
- (void) loginWithUser:(NSString*) user
password:(NSString*) password {
twitter = [STTwitterAPI twitterAPIWithOAuthConsumerKey:kOAuthConsumerKey
consumerSecret:kOAuthConsumerSecret
username:user
password:password];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *username) {
_status = [NSString stringWithFormat:#"Access granted for %#", username];
_isConnected = YES;
} errorBlock:^(NSError *error) {
_isConnected = NO;
_status = [error localizedDescription];
NSLog(#"Status: %#",_status);
}];
}
I can read direct messages using my personal Twitter account and other development Twitter account but if I try to use other Twitter account from my beta testers I can not read the direct messages.
The error message is:
This application is not allowed to access or delete your direct messages.
I tried to use an OSX system account to do login using this code:
- (void) loginWithSystemAccount {
twitter = [STTwitterAPI twitterAPIOSWithFirstAccount];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *username) {
_status = [NSString stringWithFormat:#"Access granted for %#", username];
_isConnected = YES;
} errorBlock:^(NSError *error) {
_isConnected = NO;
_status = [error localizedDescription];
NSLog(#"Status: %#",_status);
}];
}
But I can read direct messages using a system account.
I checked the OSX Demo in STTwitter git repository but I could not find a solution.
How can I do a right login in Twitter for all users to read direct messages?
Thanks in advance
At first, you should find out if it's a weird behaviour of Twitter API, or a bug in STTwitter.
To do so, I suggest that you try reading direct messages with twurl.
If you're not sure which endpoints you're calling, enable STTwitter networks logs with the STHTTPRequestShowCurlDescription argument.

Facebook login failing on iOS 6

When I try to login using Facebook iOS SDK I get the error The operation couldn't be completed (com.facebook.sdk error 2).
The state of the session is: FBSessionStateClosedLoginFailed.
THis is my code now:
-(void) callFBService{
NSArray *permissions = [[NSArray alloc] initWithObjects:#"email, publish_stream, user_likes, friends_likes", nil];
[FBSession openActiveSessionWithReadPermissions:permissions allowLoginUI:YES
completionHandler:^(FBSession *fbsession,
FBSessionState status,
NSError *error) {
if(error)
{
NSLog(#"Session error");
[self fbResync];
[NSThread sleepForTimeInterval:0.5]; //half a second
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *fbsession, FBSessionState status, NSError *error) {
[self sessionStateChanged:fbsession state:status error:error];
}];
}
else
[self sessionStateChanged:fbsession state:status error:error];
}];
}
I have tried everything in the following posts:
The operation couldn’t be completed. (com.facebook.sdk error 2.) ios6
Facebook Registration : The operation couldn't be completed (com.facebook.sdk error 2)
Facebook SDK 3.1 iOS: Handle login if user remove app from Facebook Settings
Any ideas??? Please!
You're passing publish_stream in with read permissions, but publish_stream is a write permission. It's also deprecated (use publish_actions instead). Try removing that permission. You'll need to ask for that permission separately, after you get your user logged in with read permissions. See the SDK docs: https://developers.facebook.com/docs/technical-guides/iossdk/login/#read
In addition, a few things to check: Make sure your app on Facebook.com is configured correctly, including the bundle ID. Make sure the user you're attempting to log in has rights to the app (if the app is in sandbox mode, make sure the user is added as a tester and has approved this).

How to specify the app name user was using to post - (via app name) using SDK 3.1

Using the new Facebook SDK 3.1 and iOS 6 there are 2 (actually 3) ways to post.
(Seems the new trend is to have more options to make it more simple??) OMG!!
Here is one:
SLComposeViewController *fbPost = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[fbPost addURL:[NSURL URLWithString:href]];
[self presentViewController:fbPost animated:YES completion:nil];
And this is another way using native dialogs:
[FBNativeDialogs presentShareDialogModallyFrom:self
initialText: nil
image: nil
url: [NSURL URLWithString:href]
handler:^(FBNativeDialogResult result, NSError *error) {
if (error) {
}
else
{
switch (result) {
case FBNativeDialogResultSucceeded:
break;
case FBNativeDialogResultCancelled:
break;
case FBNativeDialogResultError:
break;
}
}
}];
We, developers, think this is cool because we give a nice functionality to the user and also because our app name appears in the post and that can make some promotion of the app.
The funny thing is that latest implementations are not allowing to specify the app name was posting, the name appears after 'via'.
I tried aswell using SLRequest:
ACAccountStore *store = [[ACAccountStore alloc] init];
ACAccountType *fbType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
(options)[#"ACFacebookAppIdKey"] = kFacebookAppID;
(options)[#"ACFacebookPermissionsKey"] = #[#"publish_stream"];
(options)[#"ACFacebookAudienceKey"] = ACFacebookAudienceFriends;
[store requestAccessToAccountsWithType:fbType options:options completion:^(BOOL granted, NSError *error) {
if(granted) {
// Get the list of Twitter accounts.
NSArray *fbAccounts = [store accountsWithAccountType:fbType];
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
(params)[#"link"] = href;
// (params)[#"picture"] = picture;
// (params)[#"name"] = name;
(params)[#"actions"] = #"{\"name\": \"Go Gabi\", \"link\": \"http://www.gogogabi.com\"}";
//Set twitter API call
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST
URL:[NSURL URLWithString:#"https://www.facebook.com/dialog/feed"] parameters:params];
//Set account
[postRequest setAccount: [fbAccounts lastObject]];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if(error)
{
NSLog(#"%#", error.description);
}
else
{
NSLog(#"%#", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
}
}];
} else {
}
}];
Unfortunatelly to share that name is not so trivial anymore, I wonder why and who was designing the new implementation...
I would appreciate to get some help on that, thanks in advance.
I try to make my questions funny because is soo boring spend time in so trivial topics...
When you use the SLComposeViewController, it's actually the system presenting to you their controller, and it's the user who sends using the post button. Therefore on Facebook it appears as "via iOS".
There's no way to change that.
Using the Facebook SDK 3.1, under the hood it is also using the iOS 6 native integration, so when you're calling the FBNativeDialogs, on iOS 6, it's using SLComposeViewController.
Facebook continued to develop their SDK because they provide a couple of nice modules to use "out of the box" - this includes friends list selector etc... But I believe the biggest reason for Facebook to continue supporting their SDK it for backward compatibility. Under the hood if you're not on iOS 6, it falls back to it's library, and if you are on iOS 6, it uses the system integration.
Facebook is a big thing, and now it's natively available a lot of developers will be using it, just like Twitter's integration last year. The problem of course is at that point the developer has the option to drop older iOS support, or... have a lot of duplicate code, in the sense that they will check for SLComposeViewController and if it's not available (iOS 5) then use the old Facebook SDK... You can imagine how this would become very messy very quickly.
So, the Facebook SDK (3.1) is using iOS system Facebook integration if available, or if not, it's own. In a nutshell, unless you really want the Facebook SDK goodies (friend picket to name one), and you're not planning on supporting iOS < 6 then you don't need to worry about their SDK, just use the Social framework.
So, back to your question, there are 3 ways to post to Facebook ? Actually taking into consideration what I mentioned, there are 2 ways in iOS 6: SLComposeViewController or, SLRequest. On older iOS versions, only 1: Facebook SDK.
Since the SLComposeViewController is owned by the system, not your app, it will always share as "via iOS".
On the other hand SLRequest will show your apps name. When you specify an account for your SLRequest, that account was acquired via the ACAccountStore as a result of passing in some options including ACFacebookAppIdKey, which will be used to determine your Facebook apps name to post onto the users feed as part of the post.
Hope this helps.

Access Facebook Accounts on OS X Mountain Lion

As Mountain Lion now officialy has Facebook integrated I wanted to play a little bit with Accounts.framework and Social.framework of OS X.
I set up an App in the Facebook Developer App and used the following code to request access to the Facebook Accounts of the logged in user:
ACAccountStore *acStore = [[ACAccountStore alloc] init];
ACAccountType *accType = [acStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:FB_APP_ID, ACFacebookAppIdKey, #"read_stream, publish_stream", ACFacebookPermissionsKey, ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
[acStore requestAccessToAccountsWithType:accType options:options completion:^(BOOL granted, NSError *error) {
if (granted) {
NSLog(#"Accounts: %#", acStore.accounts);
NSLog(#"Access granted");
} else {
NSLog(#"Access denied");
}
}];
Now I always get the error Error Domain=XPCObjectsErrorDomain Code=2 "The operation couldn’t be completed. (XPCObjectsErrorDomain error 2.)"
When I launched the App from Xcode the first 2-3 times, OS X displayed the confirmation dialog "XYZ wants to access your Facebook Accounts", I clicked ok and I got an error saying something like "The Application is not yet installed". This error now "disappeared" and I'm getting the error noted above.
My question is: Do I have to configure something special in my Xcode Project (Info.plist) or in the Facebook Developer App to make it work with OS X? Or am I missing something in the code? Samples and Tutorials regarding this seem to be very rare :-/
I already watched the WWDC 2012 Video about the Twitter/Facebook Integration but it uses almost exactly the code I used.
Any help is appreciated :-)
Cheers,
Björn
Update
I solved the issue, I just did not read the docs carefully enough ;-) I have to pass the permissions as an NSArray and not as a string. I've modified the options dictionary to look like this:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
FB_APP_ID, ACFacebookAppIdKey,
[NSArray arrayWithObjects:#"read_stream", #"publish_stream", #"email", #"user_likes", nil], ACFacebookPermissionsKey,
ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
Now OS X shows an alert that asks me if I want to allow the App to post to Facebook on my behalf, I click OK and a new error appears resulting in no access to the Facebook accounts:
Error Domain=com.apple.accounts Code=7 "The Facebook server could not fulfill this access request: The app must ask for a basic read permission at install time."
I already modified the permissions to be just email or just user_likes but it all resulted in the same error. If I only request access to read_stream the access gets granted but results in the OAuth error 190 with the message Error validating access token: User XXXXXX has not authorized application XXXXXX.
Update 2:
I now solved all my problems, see my answer below.
Alright, I finally solved it :-)
When you first request access to a users Facebook accounts, you may only request permissions from the user listed under "User and Friend permissions" in Facebook's Permission Reference.
Once the user granted access and with that also installed the application on Facebook, you may request any additional permissions required by your App. It's important that you may not ask for read and write permissions at the same time, one after the other! So requesting the permission read_stream and publish_stream in the same request will not work.
This is the basically the code I used:
self.store = [[ACAccountStore alloc] init];
ACAccountType *accType = [self.store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSMutableDictionary *options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
FB_APP_ID, ACFacebookAppIdKey,
[NSArray arrayWithObjects:#"email", #"user_about_me", #"user_likes", nil], ACFacebookPermissionsKey, ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
[self.store requestAccessToAccountsWithType:accType options:options completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
self.accounts = self.store.accounts;
[options setObject:[NSArray arrayWithObjects:#"read_stream, read_mailbox, read_requests", nil] forKey:ACFacebookPermissionsKey];
[self.store requestAccessToAccountsWithType:accType options:options completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
completionHandler(granted, error);
} else {
NSLog(#"Access denied 2");
NSLog(#"%#", [error description]);
}
}];
} else {
NSLog(#"Error: %#", [error description]);
NSLog(#"Access denied");
}
}];
Hope this will help somebody :-)
I would like to add that there is an additional caveat in the Facebook docs:
// if a user has *never* logged into your app, you MUST include one of
// "email", "user_location", or "user_birthday". Other read
// permissions can also be included here.
Failure to do this leads to the same error.