Game Center multiplayer, very long connection timeout - iphone

I've implemented a 2-player turnbased game using Game Center matchmaking/multiplayer, in other words using GKMatch. It works well. There is just one issue: when one player disconnects (ie. quits the app), it takes a while before the other players gets notified of this (with match:player:didChangeState:). Sometimes even 30 seconds.
That is not a good UX. I don't want a player to wait for nothing if the other player already disconnected 30 seconds ago.
2 questions:
Is this an issue with the sandbox server only?
If not, what can I do to shorten/eliminate this waiting period?

I did not rely on GC's notifyPlayer.. Everything from DC to quit game to receive calls i handle by my own codes..
for my code, when player A presses home button, means in app delegate's applicationDidEnterBackground, a data is sent to the player B to inform that player A has quit the game. This way, when the player A quits, player B will immediately know that player A has quit.. Rather than waiting for gamecenter to notify you..

Related

GKTurnBasedMatch in a new game can i wait until another player has accepted my invitation?

I'm writing the multiplayer part of a turn based game,i'm using game center to manage the matches. Starting a new game with GKTurnBasedMatch do not send immediatly the invite notification to the other player. To send the notification i have to made my move and end first turn... Can i modify this behaviour? I wanna made my first turn only if the other player has already accept my invitation.
One way of appearing to do this would be to add a value in the NSData, say an int, that remembers what turn number it is. Start your game, then end your turn immediately without showing anything to the user. All it does is increments the turn number. When the other player accepts, if the turn number says its the second turn, increment the turn number again, and end their turn. Continue this end-increment-end pattern until the first player receives the turn back, then start playing normally, with all players having accepted the invitations and officially joined the game.
I do not recommend doing this, as this can cause a significant delay in the play time for the players who are ready to begin. They may expect it from your game eventually, but the standard pattern has a shorter apparent waiting time for the players to begin playing.
You can check the status property of the other participant who is of class GKTurnBasedParticipant. If its status continues to be GKTurnBasedParticipantStatusInvited, forbid yourself from opening the game controller and display an alert.
GKTurnBasedParticipant documentation

iPhone: What is MPMusicPlaybackStateInterrupted? And what is difference between it and MPMusicPlaybackStatePaused

I have some questions about MPMusicPlayerController's playbackState properties.
In the document, MPMusicPlaybackStateInterrupted and MPMusicPlaybackStatePaused are defined as follows:
MPMusicPlaybackStateInterrupted
The music player has been interrupted, such as by an incoming phone call.
MPMusicPlaybackStatePaused
The music player is paused.
I can't check incoming phone call because I don't have iPhone now.
But only a few times I got MPMusicPlaybackStateInterrupted state while just playing music with iPod touch.
(I don't know why the interrupted state happened. There was no incoming phone call and no other operations except for just playing music).
And at those times, MPMusicPlayerController just paused playing music.
Question1
What is the difference between MPMusicPlaybackStateInterrupted and MPMusicPlaybackStatePaused?
Question2
When does MPMusicPlaybackStateInterrupted happen except for incoming phone call?
Question3
What should I do when I get MPMusicPlaybackStateInterrupted?
For example, when I get MPMusicPlaybackStatePaused or MPMusicPlaybackStateStopped, I should change play/pause button.
I confirmed the following information with iOS 5.1.1.
Question1
What is the difference between MPMusicPlaybackStateInterrupted and MPMusicPlaybackStatePaused?
MPMusicPlaybackStatePaused happens when the player paused.
MPMusicPlaybackStateInterrupted happens when the player is interrupted by other audio output such as incoming phone call or timer of Apple's Clock app.
Question2
When does MPMusicPlaybackStateInterrupted happen except for incoming phone call?
MPMusicPlaybackStateInterrupted happens when timer of Clock app rings.
-applicationWillResignActive: also is called when the timer rings.
But MPMusicPlaybackStatePaused doesn't happen and playing music is automatically resumed after interruption (the alarm of the timer) finished.
Other examples of interruption are Siri/Voice Control(hold down home button), remote control of earphone(if you use applicationMusicPlayer), incoming phone call.
Pushing play button of remote control of earphone doesn't make the app resign active. And the interruption never finish.
MPMusicPlaybackStateInterrupted doesn't happen and playback state doesn't change when notification banner appears on top of the screen.
VoiceOver also doesn't generate interruption.
Question3
What should I do when I get MPMusicPlaybackStateInterrupted?
For example, when I get MPMusicPlaybackStatePaused or MPMusicPlaybackStateStopped, I should change play/pause button.
You don't have to do anything in callback of MPMusicPlayerControllerPlaybackStateDidChangeNotification when MPMusicPlaybackStateInterrupted happens.
Because playing music is automatically resumed after interruption.
EDIT
I found that infrequently playing music is not resumed automatically.(That means you can't rely on automatic resume.)
And in the following cases playing music is not resumed automatically.
When remote control button of earphone was pushed. (if you use applicationMusicPlayer)
When timer rang, you double-tap home button, switch application, stop timer, and switch back to the application.
When you switched back to the app while you are calling after you accepted incoming call.

Reconnect player in Game Center

I'm having trouble figuring out how to reinvite a disconnected player in a good way, using the GKMatch class for the Game Center. The game is a 1 vs. 1 game.
When I detect a disconnected player, I try to reinvite that specific player to the match with this call:
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:theMatch matchRequest:request completionHandler:^(NSError *error)
This works as it's supposed to do. When the other player has established the connection he gets reinvited and the match can continue. But this leaves a problem I haven't been able to solve. Here comes the scenario:
Player 1 disconnects.
Player 2 leaves the match while Player 1 is disconnected.
Player 1 reconnects and detects that he lost connection to Player 2 and tries to reconnect to player2.
Player 2 is looking for a new match, which he is doing with the matchmakerViewController.
Player 2 suddenly joins the old match with Player 1, which he had left.
So my problem is that the matchmakerViewController let's players join old matches if they're reinvited. Is there a better way to handle this reconnection scenario so people won't get invited back to old matches?
You could provide an option to the player that still is connected, to either re-invite, or quit. You could also remove the matchmaking request to the player that left if the other player leaves.
I would go ahead and prevent the reinvite from Player 1 on the same game if I detected Player 2 has used the quit function instead of timing out on a disconnect.

Gamekit continue session when enter background

i establish a connection between two iOS devices with GameKit and GKMatch for a synchronous game. When one player enter the background the connection will disconnect. How can I avoid this behavior? Is it possible to keep the connection via GKMatch alive while one user did suspend the app to the background?
According to Apple's documentation:
As soon as your game moves to the background, the value of the local player object’s authenticated property becomes and remains invalid until your game moves back to the foreground. You cannot read the value to determine if the player is still authenticated until Game Kit reauthenticates the player and calls your authentication handler. Your game must act as though there is not an authenticated player until your completion handler is called. Once your handler is called, value stored in the authenticated property is valid again.
Source: Game Center Programming Guide, pg. 39.
Unless your App employs VOIP or special circumstances apply, you shouldn't really be keeping a network connection open in the background. (If you are interested though, check out this SO question for a hacker-ish way of going about that).
As your player authentication is invalidated on entering the background, another device (if it does manage to receive network data from the background App) will not (reliably) know which GKPlayer sent the information.
So while Apple don't come out and say it explicitly, all Game Center features should normally be cancelled when the Application enters the background, and resumed once the player is re-authenticated upon relaunch.
As a side note, when an App withdraws to the background it is (usually, depending on background tasks) deemed "eligible for suspension". This is one reason there are such restrictions on multitasking execution - your App could be killed at any moment to free memory and you don't really want a heavy duty data transfer going on when that happens!
See TN227 if you'd like to know more about networking and multitasking.
EDIT: An alternate method:
While it is not possible to keep a GKMatch alive while an App is running in the background, an alternative way to emulate this behaviour would be to save game state to your own server. Ask the user to interact with some UI (press a button maybe) before she/he leaves the game, which saves the current game state to your own server and notifies the other player that you are about to leave the game. Upon relaunch, query your server to see if you have any saved games, and if so, load the game state and send a notification to the other player. This doesn't strictly maintain the same game, but is one way of approximating the behaviour you're after.
This is not possible
you can do like when one player enter in background
in this event
- (void) applicationDidEnterBackground:(UIApplication *)application { }
send the message to the second player in packet data that first player goes in background
then in
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context;
{
}
when perticuler that data get stop your application and pop to previous view

Multitasking: Stop Background Audio at Specific Time

I am developing an iphone app which uses background audio (on an infinite loop) to continue playing after the app has entered the background.
My problem is I want to implement a "sleep timer" which stops playback after a specified period of time.
Is this possible? I have spent an hour looking for a method to do this with no avail.
EDIT: My current thought is to use a lower level API, the Audio Queue Services, and manually re-fill the queue with another instance of the loop during the AudioQueueOutputCallback. If the timer has expired I do not fill the loop. I'm assuming this should work since the documentation says audio callbacks are still fired when an app is playing multitasking background audio. Can anyone think of a better way or a reason why this wouldn't work?
While you queue sound data on the background your app remains fully functional and running as if it was in the foreground (well almost), so yes, you should just write a timer that stops the playback at a given time and it will be fired as expected.
Now to the second question: once you stop queueing things up, your app will be "frozen" until the user manually brings it to the foreground... So what you should do is start queueing audio data from the second file before the first one is done playing, and if you DO need to pause or stop, maybe a solution is to play 0 bytes (silence)?
I'm not actually sure this would be allowed in the App Store. An app is not allowed to execute at all in the background, with the exception of VoIP apps and push notifications.