I use SkyDrive on my iOS app, everything works fine until I close my app and when I open it again I have to authenticate user again. I use this code:
- (id)init
{
self = [super init];
if (self) {
self.clientID = #"my id";
self.scopes = #[#"wl.signin", #"wl.skydrive", #"wl.skydrive_update"];
self.liveClient = [[LiveConnectClient alloc] initWithClientId:self.clientID
scopes:self.scopes
delegate:self
userState:#"initialize"];
}
return self;
}
This is for sign in user first time, when I click on the button:
- (void)signInFromViewController:(UIViewController *)viewController
{
if (_liveClient) {
if (self.liveClient.session == nil) {
[self.liveClient login:viewController
scopes:self.scopes
delegate:self
userState:#"signin"];
}
}
}
And LiveAuthDelegate method;
- (void)authCompleted:(LiveConnectSessionStatus)status
session:(LiveConnectSession *)session
userState:(id)userState
{
if ([userState isEqual:#"signin"]) {
if (session != nil) {
NSLog(#"Signed in");
} else {
NSLog(#"Auth error");
}
}
}
What should I do else? Maybe something in authCompleted method when userState is initialize?
I had almost exactly the same issue. The solution was to add the "wl.offline_access" scope to my initial login call.
Source code and other details can be found in the question I posted, which is here:
iOS OneDrive (skydrive) app displays permissions dialog every time it runs
Hope this helps!
Diz
Related
I am wondering how I can make the form show in my iOS App https://developers.google.com/admob/ump/ios/quick-start.
I am using Xcode vs 11.6 and exported the game from Godot game engine.
I have changed the GADApplicationIdentifier in my info.plist and I don't get any errors in my code it just doesn't show the form when I run the game. I live in Europe. Any help is appreciated.
This is my current code:
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#import "ViewController1.h"
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)start {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
}
- (void)viewDidLoad {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
[super viewDidLoad];
}
- (void)loadForm {
[UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
NSError *loadError) {
if (loadError) {
// Handle the error.
} else {
// Present the form. You can also hold on to the reference to present
// later.
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusRequired) {
[form
presentFromViewController:self
completionHandler:^(NSError *_Nullable dismissError) {
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusObtained) {
// App can start requesting ads.
}
}];
} else {
// Keep the form available for changes to user consent.
}
}
}];
}
#end
EDIT
Add a few NSLog to see what gets called.
try the following - just a stone into the bush, maybe it hits something ...
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#import "ViewController1.h"
#include <UserMessagingPlatform/UserMessagingPlatform.h>
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)start {
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
} else {
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
[self loadForm];
}
}
}];
}
// Change this one
- (void)viewDidLoad {
[super viewDidLoad];
}
// Add this one
- ( void ) viewDidAppear:( BOOL ) animated {
[super viewDidAppear:animated];
// View controller is now visible and on screen, so request permission
self.addMobStuff;
}
// Change / add this one
- ( void ) addMobStuff {
NSLog( #"addMobStuff" );
// Create a UMPRequestParameters object.
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
// Set tag for under age of consent. Here #NO means users are not under age.
parameters.tagForUnderAgeOfConsent = #NO;
// Request an update to the consent information.
if ( ! UMPConsentInformation.sharedInstance )
{
NSLog(#"No shared instance");
}
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable error) {
if (error) {
// Handle the error.
NSLog(#"Some error %#", error);
} else {
NSLog(#"Proceed to form ...");
// The consent information state was updated.
// You are now ready to check if a form is
// available.
UMPFormStatus formStatus =
UMPConsentInformation.sharedInstance
.formStatus;
if (formStatus == UMPFormStatusAvailable) {
NSLog(#"Loading form ...");
[self loadForm];
}
else {
NSLog(#"Form status is not available");
}
}
}];
}
- (void)loadForm {
[UMPConsentForm loadWithCompletionHandler:^(UMPConsentForm *form,
NSError *loadError) {
if (loadError) {
// Handle the error.
NSLog(#"Form error %#", error);
} else {
// Present the form. You can also hold on to the reference to present
// later.
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusRequired) {
NSLog(#"Presenting form");
[form
presentFromViewController:self
completionHandler:^(NSError *_Nullable dismissError) {
if (UMPConsentInformation.sharedInstance.consentStatus ==
UMPConsentStatusObtained) {
// App can start requesting ads.
}
}];
} else {
// Keep the form available for changes to user consent.
NSLog(#"Changes");
}
}
}];
}
#end
note if this works it probably needs a bit more polish before it can be released into the world but hopefully at least the request form will be displayed ...
I created a class of NSObject and I have this authenticate function in it:
-(void)authenticateLocalUser {
if(!gameCenterAvailable) { return; }
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
__weak GKLocalPlayer *blockLocalPlayer = localPlayer;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
NSLog(#"authenticateHandler");
if (viewController != nil)
{
NSLog(#"viewController != nil");
}
else if (blockLocalPlayer.isAuthenticated)
{
NSLog(#"localPlayer already authenticated");
//do some stuff
}
else
{
NSLog(#"local player not authenticated");
// not logged in
}
};
}
Its the new version i looked up , but its not displaying the Game Center login form.
Im calling this method in my AppDelegate.m if you need this information.
I think I have to put something in there when the player is not logged in like get the login form. But I don't know how.
Thanks for any help!
There are two things you need. First, you need to check error. If it is set, the viewController will usually be nil and your code will incorrectly assume that you're logged in and communicating happily Game Center. You may appear logged in based on cached credentials, but in most cases, you won't actually be seeing current data from the server, you'll just have access to whatever data was last cached on the device.
Second, you have to present the viewController to the user if they're not logged in. Try this:
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
NSLog(#"authenticateHandler");
if (error)
{
//Examine the error. IOS may show you as "authenticated" based on
//cached credentials, but you probably can't really communicate with
//game center in any meaningful manner
}
else if (viewController != nil)
{
//You're not logged in, show the login viewController
NSLog(#"viewController != nil");
UIViewController *mainVC = [[[[UIApplication sharedApplication]delegate] window] rootViewController];
[mainVC presentViewController:viewController animated:NO completion:^
{
//the login view controller has been dismissed. Did it work?
if ([GKLocalPlayer localPlayer].authenticated)
{
//Yes, Login worked. enable whatever comes next after successful login
}
else
{
//No, login failed or was canceled.
}
}];
}
else if (blockLocalPlayer.isAuthenticated)
{
NSLog(#"localPlayer already authenticated");
//do some stuff
}
else
{
NSLog(#"local player not authenticated");
// not logged in
}
};
I'm implementing v4.1 of the SDK for iOS and when I try to call for publishPermissions:, I get no callback.
For some reason everything works perfectly when I run logInWithReadPermissions:, but when I run logInWithPublishPermissions: it never hits my response handler. Nothing happens.
To test things out, I reset my loginManager before running logInWithPublishPermissions:, and to my surprise it worked then (aka NSLog(#"RESULT") is called).
Am I missing something about how the loginManager works? Shouldn't I be able to use it without resetting it?
// FacebookController.m
#implementation FacebookController
FBSDKLoginManager *loginManager;
static FacebookController *_shared = nil;
- (id)init {
self = [super init];
if (self != nil) {
userData = [[NSMutableDictionary alloc] init];
loginManager = [[FBSDKLoginManager alloc] init];
}
return self;
}
+ (id)getInstance {
if (!_shared) {
_shared = [[self alloc] init];
}
return _shared;
}
- (bool)hasPublishPermissions {
FBSDKAccessToken *accessToken = [FBSDKAccessToken currentAccessToken];
if(accessToken != NULL){
NSSet *permissions = [accessToken permissions];
if([permissions containsObject:#"publish_actions"]){
return TRUE;
}
}
return FALSE;
}
- (void)requestPublishPermissionsWithDelegate:(id)aDelegate {
if(![self hasPublishPermissions]){
// FOR SOME REASON IT WORKS IF I RESET LOGIN MANAGER AS FOLLOWS
// loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithPublishPermissions:#[#"publish_actions"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
NSLog(#"RESULT: %#", result);
}];
}
}
- (void)connectToFacebookWithDelegate:(id)aDelegate {
FBSDKAccessToken *accessToken = [FBSDKAccessToken currentAccessToken];
if(accessToken != nil){
[aDelegate performSelector:#selector(facebookSignedIn)];
} else {
[loginManager logInWithReadPermissions:#[#"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
// Process error
NSLog(#"ERROR");
} else if (result.isCancelled) {
// Handle cancellations
NSLog(#"CANCELLED");
} else {
NSLog(#"SUCCESS");
[aDelegate performSelector:#selector(facebookSignedIn)];
}
}];
}
}
#end
Edit #1:
Including videos of it working and not working for the given scenarios:
Not working (loginManager reinitialization commented out):
https://dl.dropboxusercontent.com/u/14277258/not-working.mov
Working (loginManager reinitialized):
https://dl.dropboxusercontent.com/u/14277258/working.mov
Your video stack trace indicates you're calling the request for publish permissions inside the handler for your initial login. This should be avoided:
You're causing another login after the user has already granted you some permissions - it's not very good for the user to have to see another login dialog immediately after completing one.
You're asking for publish permissions when you don't need it - this may violate Facebook developer policies and again is not the best user experience. Instead you should asking for publish only when you need it (i.e., at the time of sharing).
If you really insist, you can dispatch your second login call asynchronously so that the first request finishes entirely but I wouldn't recommend it. We can probably update the SDK to detect this and log though so it's not as confusing.
I would like to ask users if they would like to enable FB integration and provide a UISwitch for them to indicate their preference. However, I only want to have that option enabled/unhid in the event that the user has actually set up their FB account in the iPhones settings. How does one go about checking to see if they have even done that much?
give it a try this will help you .....
if(iOSVersion >= 6.0)
{
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
NSLog(#"user have filled fb acount details");
}
else
{
NSLog(#"settings is empty");
}
}
I figured it out. Here is the block of code that works for me. I welcome suggestions for improvement :)
self.myStore = [[ACAccountStore alloc] init];
ACAccountType *acct = [self.myStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSArray *fbAccounts = [self.myStore accountsWithAccountType:acct];
// Check to make sure the user has a FB account setup, or bail:
if ([fbAccounts count] == 0) {
userDoesNotHaveFBAccountSetup = YES;
self.fbSwitch.enabled = NO;
[[self fbSwitch] setOn:NO];
[self viewDidLoad];
} else {
userDoesNotHaveFBAccountSetup = NO;
self.fbSwitch.enabled = YES;
}
The issue I have is that after users tap on the "Share" button of the FBDialog, they do not get any visual feedback until the request completes or fail... and over 3G that can takes a while. During this time users do not know if they tapped "Share" correctly or not, and there's risk of posting content twice.
Is there a way I can get a callback so I can display a loading indicator during this time? Where should I put this piece in?
Thank you!
Below code you write to fbAgent.m and also obser code here u get one "PID" at that time u write to alert msg ....... user can understand to that msg was success posted Facebook.
I hope this helps.
- (void)request:(FBRequest*)request didLoad:(id)result {
if ([request.method isEqualToString:#"facebook.fql.query"]) {
NSArray* users = result;
NSDictionary* user = [users objectAtIndex:0];
NSString* name = [user objectForKey:#"name"];
// Calling the delegate callback
[delegate facebookAgent:self didLoadName:name];
} else if ([request.method isEqualToString:#"facebook.users.setStatus"]) {
newStatus = nil;
NSString* success = result;
if ([success isEqualToString:#"1"]) {
// Calling the delegate callback
[delegate facebookAgent:self statusChanged:YES];
} else {
[delegate facebookAgent:self statusChanged:NO];
}
} else if ([request.method isEqualToString:#"facebook.photos.upload"]) {
NSDictionary* photoInfo = result;
NSString* pid = [photoInfo objectForKey:#"pid"];
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[NSString stringWithFormat:#"success Uploaded Your image please check your FaceBook", pid] delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
[alertView release];
fbbut.enabled=YES;
[fbact stopAnimating];
self.uploadImageData = nil;
self.uploadImageCaption = nil;
self.uploadImageAlbum = nil;
//[delegate facebookAgent:self photoUploaded:pid];
if(newStatus){
[self setStatus:newStatus];
}
}
}
Start your indicator when you click on button and stop on Delegate of Facebook function
- (void)dialogDidComplete:(FBDialog *)dialog
Hope it helps....