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!
Related
I am trying to create a function with iOS facebook sdk where I will be able to login and if I am logged in I will be able to see the nslog string "logged in". However I am not seeing it the string at all. Also, the login seems to be working fine in terms of pushing button and seeing my Facebook app and pressing ok to continue. Can someone inform me on what I am doing wrong?
-(IBAction)popButton:(id)sender {
TUAppDelegate *appDelegate = (TUAppDelegate *)[[UIApplication sharedApplication] delegate];
// this button's job is to flip-flop the session from open to closed
if (appDelegate.session.isOpen) {
// if a user logs out explicitly, we delete any cached token information, and next
// time they run the applicaiton they will be presented with log in UX again; most
// users will simply close the app or switch away, without logging out; this will
// cause the implicit cached-token login to occur on next launch of the application
[appDelegate.session closeAndClearTokenInformation];
} else {
if (appDelegate.session.state != FBSessionStateCreated) {
// Create a new, logged out session.
appDelegate.session = [[FBSession alloc] init];
}
// if the session isn't open, let's open it now and present the login UX to the user
[appDelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// and here we make sure to update our UX according to the new session state
[self updateView];
}];
}
}
- (void)updateView{
// get the app delegate, so that we can reference the session property
TUAppDelegate *appDelegate = (TUAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.session.isOpen) {
NSLog(#"Logged In");
} else {
NSLog(#"Not Logged In");
}
}
I suspect you've missed at least step 2d, wiring the openURL back to the Facebook SDK:
https://developers.facebook.com/docs/tutorials/ios-sdk-tutorial/authenticate/
... that said, you could easily have missed more. If you are seeing your app again after login then I suspect you've added the URL scheme to your Info.plist, otherwise check that also.
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);
};
I have a popular medicine app often used by med students and residents at the bedside. I incorporated the new FB SKD into my last updated which, when opened for the first time (and subsequently if not used for a few days), opens the native FB app then redirects to my app. Many customers have complained because the info within the app often needs to be looked up quickly (crashing patient).
Is it possible to set up my app so the user needs to click on a button within the app before connecting to FB? Thanks!
I think you will need to make change to authorizeWithFBAppAuth method in facebook.m file of the SDK.
This SO has a suggestion for you.
When you download the FB SDK you get a sample project. Compile and run it, and you should see a toggle button that allows user to login/logout. You've got the FB official images in that project, and the code behind it is pretty simple:
/**
* Called on a login/logout button click.
*/
- (void)fbButtonClick:(id)sender {
if (fbButton.isLoggedIn) {
[self logout];
} else {
[self login];
}
}
/**
* Show the authorization dialog.
*/
- (void)login {
[_facebook authorize:nil delegate:self];
NSLog(#"Sas");
}
/**
* Invalidate the access token and clear the cookie.
*/
- (void)logout {
[_facebook logout:self];
}
You should also change the button's state in the FBAuth delegate methods (which you've already implemented) by calling a method similar to this one:
- (void)updateFbButtonAccordingToSessionStatus {
//Check if session is valid and update button accordingly
if ([self.facebook isSessionValid] == NO ) {
fbButton.isLoggedIn = NO;
[fbButton updateImage];
}
else {
fbButton.isLoggedIn = YES;
[fbButton updateImage];
}
}
Hope this helps.
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.
I have an app that I want to be able to connect to Facebook and post to the user's wall. I have the following code:
- (void)viewDidLoad {
static NSString* kApiKey = #"PRIVATE";
static NSString* kApiSecret = #"PRIVATE";
_session = [[FBSession sessionForApplication:kApiKey secret:kApiSecret delegate:self] retain];
// Load a previous session from disk if available. Note this will call session:didLogin if a valid session exists.
[_session resume];
// Set these values from your application page on http://www.facebook.com/developers
// Keep in mind that this method is not as secure as using the sessionForApplication:getSessionProxy:delegate method!
// These values are from a dummy facebook app I made called MyGrades - feel free to play around!
[super viewDidLoad];
}
- (IBAction)postGradesTapped:(id)sender {
_posting = YES;
// If we're not logged in, log in first...
if (![_session isConnected]) {
self.loginDialog = nil;
_loginDialog = [[FBLoginDialog alloc] init];
[_loginDialog show];
}
// If we have a session and a name, post to the wall!
else if (_facebookName != nil) {
[self postToWall];
}
// Otherwise, we don't have a name yet, just wait for that to come through.
}
The problem I have is that when the user clicks the button associated with the IBAction it will pop up the login dialog, but then the window disappears without ever pulling up the Publish Story to Wall dialog. How do I get it to login and then pull up the Publish Story to Wall?
I think you may need to use FBPermissionDialog to ask for "post to wall" permission first (I'm not sure what the exact string is; it might be in the examples).
Also note that "FBSession" is the old "iPhone" SDK (last updated in April); there's a newer "iOS" SDK at http://github.com/facebook/facebook-ios-sdk
I once encountered this behavior when my Security Key was wrong (in the new API you don't need it, but if you're based on old API it still requires it).
Make sure you use "App Id" and "App Secret" from the Facebook app control page. (And not "API Key")
Good luck!