Allow Authenticated IOS Game Center Users to Auto-Authenticate - iphone

I am making an iphone app (a game) and while it will not be my first game, it will be my first game that uses a network connection (I intend on adding a few multiplier features)
So, now for my question.
I want the player to be able to open my app, sign into game center, and then use that to connect to my server. Is this possible? In other words:
Player signs in to game center
Sends username to my server
if (game center username doesnt exist)
{
Add their username to my sql database
}
else if (username does exist)
{
Send sign in successful message to device.
}
I believe I read another question from a while ago asking how to do this, but the answer said something about using the device UDID, which I do not want to do (for obvious reasons if you read technology related news).
So anyway, is there a trusted way that I can be sure that the user is who they say they are once they authenticate with game center that I can use to authenticate them against my server? Thank you

I think instead of UDID you can use GKPlayer.playerID which is unique to each gamecenter account. For your other purposes you can customize the completion block of authenticate handler
GKLocalPlayer * __weak localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (viewController != nil)
{
[currentViewController presentViewController:viewController animated:YES completion:nil];
}
else if (localPlayer.isAuthenticated)
{
NSLog(#"Player authenticated");
/* Your custom methods here
Sends username to my server -- send localPlayer.playerID to your server
if (game center username doesnt exist)
{
Add their username to my sql database
}
else if (username does exist)
{
Send sign in successful message to device.
}
*/
}
else
{
NSLog(#"Player not authenticated");
//disableGameCenter
}
NSLog(#"Error: %#",error);
};

Related

Login in iPhone App via GameKit

I want to login to my app via GameCenter Login API.
Is it possible ?
Is Apple game Center login API public?
If you're using iOS 6, see the documentation for GKLocalPlayer. You'll see that you assign a block to the 'authenticateHandler' property of localPlayer. When you assign it, if the player isn't already logged into Game Center, one of the arguments to the block (UIViewController *viewController) gets filled in with the address of a view controller that will present the regular Apple Game Center login screen. After you get that address you do presentViewController:viewController and the user sees the normal Apple login screen. When the user finishes interacting with it you get a call back to 'gameCenterViewControllerDidFinish'. The block you provide runs more than once, which makes the process pretty hard to follow, but it works. For what it's worth I'll post below a method I'm using that seems to work. It assumes either iOS5 or iOS6. It isn't be good for anything earlier than 5. OS6 is method that returns YES on iOS6 and NO otherwise. This wasn't written for public consumption so please excuse all the debugging stuff and the unexplained stuff in it.
-(void) authenticateLocalPlayer {
ANNOUNCE
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
_lastError = nil;
//iOS 6
if ( [self os6] ) {
localPlayer.authenticateHandler = ^(UIViewController *loginVC, NSError *error) {
NSLog(#"in authenticateHandler 1");
[self setLastError:error];
//... resume application responses
[[CCDirector sharedDirector] resume]; //if not paused does nothing
if ( [GKLocalPlayer localPlayer].authenticated) {
NSLog(#"in authenticateHandler 2 - local player is authenticated");
} else if (loginVC) {
NSLog(#"in authenticateHandler 3 - local player is not authenticated, will present VC");
//... pause applications responses
[[CCDirector sharedDirector] pause];
[self presentViewController:loginVC];
} else {
NSLog(#"in authenticateHandler 4 - local player is NOT authenticated, no VC returned");
}
NSLog(#"authenticateHandler error: %#", error.localizedDescription);
};
//iOS 5
} else {
if ( [GKLocalPlayer localPlayer].authenticated == NO ) {
//no completion handler because we're relying on NSNotificationCenter
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:nil];
NSLog(#"local player authentication requested");
} else {
NSLog(#"local player was already authenticated");
}
}
}
You can do that surely. there is no gamecenter API for direct use. you can show the gamecenter authentication screen and after authentication, you can proceed.

I can't get the GK authentication dialog to come up

I am really struggling with game center right now. It could be because GK as a whole has been pooping out all day (letterpress was just released!), but I can't get an auth dialog to come up:
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (viewController) {
NSLog(#"Foo 1");
[self presentViewController:viewController animated:YES completion:nil];
} else if (localPlayer.isAuthenticated) {
NSLog(#"Foo 2");
} else {
NSLog(#"Foo 3");
}
};
}
This method is hooked up to a button. When I press it, I get this in the console:
<Info>: 23:41:52.226407 com.apple.AVConference: GKSConnSettings: set server: {
"gk-cdx" = "17.173.254.218:4398";
"gk-commnat-cohort" = "17.173.254.220:16386";
"gk-commnat-main0" = "17.173.254.219:16384";
"gk-commnat-main1" = "17.173.254.219:16385";
}
Only the third option is being printed out: Foo 3. I am going nuts here. What is going on?
Doh!
I forgot that I had switched out bundle identifiers for temporary testing on my device.
You need to use the bundle identifier as specified in ITC.
Another reason you might be seeing this even when your bundle ID is correct and you are sure everything is okay with your app info on iTunes Connect could be that you are logged into a real GameCenter account instead of a sandbox account. If so, log out of GameCenter by clicking on your email and selected to 'Sign Out' then log in to one of your test accounts (set up in iTunes Connect in the 'Manage Users' section). You'll have to accept the GameCenter Sandbox terms of service (it took a moment for these terms to appear for me so be patient). Once you have done so and have logged in with a sandbox account the GameCenter dialog should start showing up!

iOS Native Facebook Share no internet callback

I'm trying to implement the native facebook share for iOS 6 and need check if a share did succeed or not. This is the code I have used:
BOOL displayedNativeDialog =
[FBNativeDialogs
presentShareDialogModallyFrom:delegate
initialText:#"test"
image:nil
url:nil
handler:^(FBNativeDialogResult result, NSError *error) {
if (error) {
/* handle failure */
NSLog(#"error:%#, %#", error, [error localizedDescription]);
} else {
if (result == FBNativeDialogResultSucceeded) {
/* handle success */
NSLog(#"handle success");
} else {
/* handle user cancel */
NSLog(#"user cancel");
}
}
}];
if (!displayedNativeDialog) {
/* handle fallback to native dialog */
}
My problem is when I try this with no internet connection available I still get the FBNativeDialogResultSucceeded
It looks like you should get an error when no internet connection is available but it seems that it doesn't work like that.
If there are some solution where I don't need to use the reachability SDK that would be great.
You'll likely have to use the reachability SDK at this point. The Facebook SDK builds on top of the SLComposeViewController for the native functionality. That view controller returns two possible choices:
SLComposeViewControllerResultCancelled
SLComposeViewControllerResultDone
SLComposeViewControllerResultDone: The view controller is dismissed and the message is being sent in the background. This occurs when the user selects Done.
So since Facebook mirrors this the success case means the user clicked done and the message has been sent in the background.
However if you run this and there is no internet connection, the user should still see a pop-up indicating that the post could not be sent due to a connection failure.

Gaming Center iphone-sdk, how to get current player's nickname?

When my app start it should promt user to log into gaming center so that I can retrieve his nickname and then use it later to display his name,
I have the following code which somehow worked once:
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer authenticateWithCompletionHandler:^(NSError *error) {
if (localPlayer.isAuthenticated)
{
// Perform additional tasks for the authenticated player.
}
}];
}
It showed a alert view with and some buttons, but it doesn't work. Help, maybe there's an easier way to retrieve current player's nickname. Thanks!!
Getting a player's alias requires authentication with Game Center. Once you have authentication, all you have to do is get your GKPlayer instance by doing this:
GKLocalPlayer *lp = [GKLocalPlayer localPlayer];
and then, just make sure authentication occurred and get your alias:
if (lp.authenticated) {
return lp.alias;
//Any other stuff you need to do with this local player's instance goes here.
}

Game Center- handling failed achievement submissions?

Im a noob in game center # games generally. Im making my second game now and implemented the game center.
If the internet is available, there is no problem, everything works well.
But just now I purposely make the internet unreachable, and when I get an achievement, obviously it does not register to the Game Center's Achievement.
How and what's the best way to handle this issue?
Thank you....
You could add the GKAchievement objects that fail to register to an array and then resend them when you get back connectivity. You should also consider committing that array to persistent storage, in case your app terminates before it has a chance to send those achievements. Try this in your completion handler:
// Load or create array of leftover achievements
if (achievementsToReport == nil) {
achievementsToReport = [[NSKeyedUnarchiver unarchiveObjectWithFile:pathForFile(kAchievementsToReportFilename)] retain];
if (achievementsToReport == nil) {
achievementsToReport = [[NSMutableArray array] retain];
}
}
#synchronized(achievementsToReport) {
if(error == nil)
{
// Achievement reporting succeded
// Resend any leftover achievements
BOOL leftoverAchievementReported = NO;
while ([achievementsToReport count] != 0) {
[self resendAchievement:[achievementsToReport lastObject]];
[achievementsToReport removeLastObject];
leftoverAchievementReported = YES;
}
// Commit leftover achievements to persistent storage
if (leftoverAchievementReported == YES) {
[NSKeyedArchiver archiveRootObject:achievementsToReport toFile:pathForFile(kAchievementsToReportFilename)];
}
}
else
{
// Achievement reporting failed
[achievementsToReport addObject:theAchievement];
[NSKeyedArchiver archiveRootObject:achievementsToReport toFile:pathForFile(kAchievementsToReportFilename)];
}
}
Hope this helps.
I see that the two answers here focus on the specific mechanisms for archiving the undelivered achievement messages. For a higher-level description of the overall approach, you can see my answer to this related question: Robust Game Center Achievement code
Achievements (and all of the gamecenter stuff like leaderboard updates) conform to NSCoding. You can store them if you get an error submitting them and submit them later. This is what apple recommends in their docs.
Your application must handle errors when it fails to report progress to Game Center. For example, the device may not have had a network when you attempted to report the progress. The proper way for your application to handle network errors is to retain the achievement object (possibly adding it to an array). Then, your application needs to periodically attempt to report the progress until it is successfully reported. The GKAchievement class supports the NSCoding protocol to allow your application to archive an achievement object when it moves into the background.
from: http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/GameKit_Guide/Achievements/Achievements.html#//apple_ref/doc/uid/TP40008304-CH7-SW13
// Submit an achievement to the server and store if submission fails
- (void)submitAchievement:(GKAchievement *)achievement
{
if (achievement)
{
// Submit the achievement.
[achievement reportAchievementWithCompletionHandler: ^(NSError *error)
{
if (error)
{
// Store achievement to be submitted at a later time.
[self storeAchievement:achievement];
}
else
{
NSLog(#"Achievement %# Submitted..",achievement);
if ([storedAchievements objectForKey:achievement.identifier]) {
// Achievement is reported, remove from store.
[storedAchievements removeObjectForKey:achievement.identifier];
}
[self resubmitStoredAchievements];
}
}];
}
}
In case anyone stumbles upon this question in the future, Apple now has sample code for submitting achievements that includes a way to archive achievements that failed to submit (due to no network connection, etc). You'll find it in the Game Center programming guide.