GameCenter login alert - iphone

In a game I am developing using GameCenter, I want to handle the following scenario:
the user starts up the game. He is shown the system alert that prompts him to log on GameCenter. He ignores it for now.
after a while, the user wants to log in to GameCenter and clicks on(for instance) the Leaderboards menu item. He choses cancel instead of Log in, for now.
the process repeats several times. Eventually the user DOES want to log in to GameCenter. He clicks the Leaderboard menu item one more time.
In my tests, I have found that the alert popup raised by the call to "authenticateWithCompletionHandler" (as invoked by Apple's sample GameCenterManager) which suggests to log in to GameCenter only appears a limited number of times(4 or 5). The last time it appears, it says "Game Center Disabled, sign in with the Game Center application to enable"Afterwards". Afterwards, calling authenticateWithCompletionHandler no longer does anything visible -no prompt at all.
Playing FruitNinja I tried to replicate this. However, in their case, the popup saying "Game Center Disabled" does appear every time I click on a GameCenter item(Achievements, for instance).
What I'd like to do is to duplicate the functionality: that is, if you are not logged in to GameCenter, to have the standard game center alert appear all the times you click on the Leaderboard menu item.
Is there a way to learn whether the standard 'log in to game center' alert has appeared, or to force it to appear at all times(and not just the first couple of tries)?

Here's an is an idea to workaround this issue:
No matter if a "GC authenticateWithCompletionHandler"-Request is cancelled
by the user tapping "Cancel" in the dialog
or due to the fact that
GC is disabled on the device (which happens after the user has cancelled the alert-dialog exactly 3 times (in iOS 5 at least))
you will always receive an NSError with code 2 saying "The requested operation has been cancelled.".
The only differentiator that i could find is the time passed between the authenticateWithCompletionHandler-Request and the the execution of the completion-Handler.
So when sending the request i am saving the time:
requestTime = [NSDate date];
and in my completion handler i measure the time lapsed:
NSDate* now = [NSDate date];
CFTimeInterval elapsedTimeSinceAuthenticationRequest = [now timeIntervalSinceDate:requestTime];
NSLog(#"time Elapsed: %f", elapsedTimeSinceAuthenticationRequest);
If the user cancelled the request, the time passed will be significantly longer compared to the time passed if GC cancelled the operation. In my tests, it took a user at least one second to cancel the dialog, whereas a GC-cancelled request took less than 0.1 seconds (on my iPhone 4)
Of course, these values may vary depending on the device the code runs on and on what else the processor is busy with at the moment. One pitfall i already examined is the application launch: If you are sending the authenticationRequest during applicationDidFinishLaunching as suggested by Apple, it took much longer for GC to cancel the request in my case, because the device is busy loading views and whatever is necessary to launch the app.
So let me know if you tried this solution and if it worked for you, as will i once i have done further testing...

The behavior is something to the effect of, after N unsuccessful attempts - disable GameCenter for the app. Restarting the app or going to login in gamecenter itself will get it back online.
I forget which doc I read this in, but there is an Apple doc out there that explains this behavior.

I couldn't find a good answer for this either, so I decided to just replicate the message once the I start getting the cancel error. This is still in development but it basically changes the button callback to display the error alert rather than display the leader-board.
Just a note, not sure if this will be approved or not since I am replicating an Apple error message.
-(void) gcLogin: (id) sender {
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
if(error) {
if([[error domain] isEqualToString:GKErrorDomain] && [error code] == GKErrorCancelled) {
[ResourceManager showAlertWithTitle:#"GameCenter Disabled" message:#"Sign in with Game Center application to enable"];
mGameCenterCancelled = YES;
}
NSLog(#"%#", [error description]);
} else {
[self updateMenu];
mGameCenterCancelled = NO;
}
}];
}

I am playing around with Game Center myself right now I have seen the very same behavior. There is nothing in the documentation saying anything about the dialog only showing up the first couple of times.
In my case I would like a way to tell beforehand if the user is already logged into Game Center, so that I can behave appropriately. But now I can not know this before the dialog is shown to the user.
Since we are running in the sandbox during development this behavior might of course be something that behaves differently during production but this is not an easy thing to find out.

May be the link will helpful (First three paragraphs):
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/GameKit_Guide/Users/Users.html#//apple_ref/doc/uid/TP40008304-CH8-SW9
The main point is in a rectangle "Important".

I'm facing the same issue. Though I couldn't find a way to enforce poping up the same dialog for logging into Game Center, I did find a way to implement a warning message saying 'gamecenter is disabled' when user clicks on a leaderboard icon:
if([GKLocalPlayer localPlayer].authenticated == NO)
{
// Prompt a warning message alert saying game center is disabled
}
else
{
// Proceed with opening leaderboard
}
Hope this helps!

It appear that iOS will disable Game Center completely and prevent it from prompting after the user chooses to Disable Game Center (the option would appear on your fifth 5th Game Center cancel sign in).
To restore the device to the original state where the login prompt will appear again. Simply sign in using the Game Center app using a normal working Game Center account (non Tester). Once you are in, Sign Out. It should start prompting you again on within your app.

Related

Is it possible to reopen a suspended app after a time delay in Swift?

I am using the following code to suspend the app.
UIControl().sendAction(Selector("suspend"), to: UIApplication.sharedApplication(), forEvent: nil)
do {
print("suspended")
} catch _ {
print("unable")
}
I was wondering is it possible to reopen the app after a certain time delay. Following code works for performing an action after time delay. But I don't know how to reopen the app at that time interval
let seconds = 300.0
let delay = seconds * Double(NSEC_PER_SEC) // nanoseconds per seconds
let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
print("time delay")
})
It's is not possible and apps with such kind of "functionality" will be rejected by Appstore ;)
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/StartingStopping.html
Always Be Prepared to Stop
An iOS app never displays a Close or Quit option
When people switch away from your app, iOS multitasking transitions it to the background and replaces its UI with the UI of the new app. To prepare for this situation, your app should:
Save user data as soon as possible and as often as reasonable. Do
this because an app in the background can be told to exit or
terminate at any time.
Save the current state when stopping at the finest level of detail possible. In this way, people don’t lose their
context when they switch back to your app. For example, if your app
displays scrolling data, save the current scroll position. You can
learn more about efficient ways to preserve and restore your app’s
state in Preserving Your App’s Visual Appearance Across Launches.
Some apps may need to keep running in the background while users run another app in the foreground. For example, users might want to keep listening to the song that’s playing in one app while they’re using a different app to check their to-do list or play a game. Learn how to handle multitasking correctly and gracefully in Multitasking.
Never quit an iOS app programmatically. People tend to interpret this as a crash. If something prevents your app from functioning as intended, you need to tell users about the situation and explain what they can do about it.

applicationMusicPlayer stops when user locks the screen on iOS 5

I set the audio session category to kAudioSessionCategory_MediaPlayback, I active the session, which returns no errors, and still the iPod music stops when I lock the device. This happens on iOS 5 GM, so I guess this will happen in the final version. On iOS 4+ the current code works fine. Any ideas how to fix this? Huge thanks :)
It's not a bug. To save power locking the phone is now treated as if the user pressed the home button. The fact that applicationMusicPlayer stops now when locking is just a side effect of this change.
To work around this problem you should switch to AVPlayer and make use iOS 4's audio in background mode.
Fixed this issue for my particular problem - how to detect the difference between OS4 and OS5 behavior when device gets to the Lock screen.
In OS4 app does 'applicationWillResignActive' but on OS5 it goes all the way to 'applicationDidEnterBackground' which looks exactly the same as the user hitting the Home button.
It turns out that if you check the UIApplicationState of the application given in '- (void)applicationDidEnterBackground:(UIApplication *)application', it has 3 possible values:
typedef enum {
UIApplicationStateActive,
UIApplicationStateInactive,
UIApplicationStateBackground
} UIApplicationState;
When the user hits home on OS5, you get UIApplicationStateBackground, but when the user hits Lock, you get UIApplicationStateInactive.
Hope that helps.
Happy Holidays everyone.

Allow application continue running when iPhone gets locked

I have developed an iPhone app which gets the microphone recorder inputs every second using NSTimer, calculate the amplitude of sound, and take appropriate action if required. I have noticed that when my iPhone gets locked, my application stops running(it doesn't fire the timer callback function). When I unlock iPhone, it start automatically. Could anyone please tell me how can I allow application responding when iPhone gets locked? Is there any other way around such that iPhone shouldn't get locked when my application is running? What should be Apple's recomendation on this?
I found this article but not sure it is correct way to do.
Thanks.
You cannot prevent timer from being stopped when application goes into idle state. Only one possible way is to disable idleTimer of the application.
application.idleTimerDisabled = TRUE;
//or
//Disable screen dimming if no user input occur on device.
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];

Game Center authentication can take a very long time. How to work around it?

Waiting for Game Center authentication to complete is a bad idea since it can take a very long time. Moreover, authentication is done not just at game launch but whenever you switch back to a game via fast app switching.
But not waiting for authentication presents problems:
how do you resume a saved game if you don't know who the player is? Ideally, a saved game would be associated with who was playing so you don't have someone resuming another person's game.
how do you resume a game after an app switch back if you don't know who the player is (the player may have changed via the Game Center app)?
a Game Center log in alert might pop up in the middle of an action game (it is not paused)
what if the game is over before authentication completes? What if the initial authentication completes after a few games have been played? What if the initial authentication completes after an app switch or two (which in turn result in more authentications)?
What is a reasonable approach to handle these problems?
Hmm.. i only authenticate at the start of app.. Its set by yourself when you want to authenticate the player.. You might want to save the player alias when the player is first authenticated.. Means:
sharedData.myName = [[GKLocalPlayer localPlayer]alias];
So when the player app switch and stuff, but is not authenticated, you save data under this player alias.. So when the player is finally authenticated, you send the data to GameCenter
Meaning in your checking GameCenter part..
if(!inGame)
{
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error){
if(error == nil){
if(sharedData.myName ==nil)
{
sharedData.myName = [[GKLocalPlayer localPlayer]alias];
}
else if([[GKLocalPlayer localPlayer]alias] == sharedData.myName)
{
[self sendSavedData];
}
else if([[GKLocalPlayer localPlayer]alias] != sharedData.myName)
{
// create new data or look for other saved data which has the same name..
// set sharedData.myName to current player Name..
}
}
enter code here

App not playing sound when screen turned off, but doing everything else as it should?

I have an alarm clock app which works on a timer. When the alarm is meant to go off and the screen is switched off, it should start playing audio from AVAudioPlayer, but it doesn't. Then when i turn the screen back on, i can see that the rest of the code fired as expected (a stop button is now on the screen). How do i get the AVAudioPlayer to play when the screen is turned off?
Is there any way for me to detect that the screen is turned off?
#zoul is correct that using the default audio session category will result in sound form your app being disabled when the user locks the screen. See the Audio Session Programming Guide for direction on which audio session category you should choose.
However, even once your audio session category is set correctly, you'll have another issue to tackle. When the screen is switched off, your application gets suspended per Apple's documentation here: Executing Code in the Background. This means that when the user locks their phone or switches to a different app, your app will stop running and stay in a freeze-dried (task-suspended) state until the user activates your app again. At that point, your app resumes execution as if nothing happened. That's why it appears that your app has continued to function when you unlock the screen.
For alarm behavior, you'll probably want to schedule the delivery of a local notification. A local notification will ensure that the system provides your alert to the user at the time you request, and allows the user to activate your app. See Scheduling the Delivery of Local Notifications for details on how to accomplish this.
Maybe you have the wrong audio category? See the documentation for AVAudioSession, especially the audio category settings.