Home Button doesn't terminate multiplayer match on Game Center / Gamekit - notifications

First of all I have to say I am new to iOS development.
My problem is during a multiplayer game using Game Center. I don't now how to get a notification from Game Center if the other player (my game is a 2 player game) leaves the game with the home button of the device.
I need to know when one player closes the game since the game always starts from scratch when re-opened, this means, it will show the splash screen and go directly to the main menu. I've tried re-matching but Game Center seems to be creating a new connection and looking for new players, meanwhile player 2 keeps 'playing' with player 1 without any response happening, so his match will never end.
Any method, didChangeState, matchmakerViewControllerWasCancelled nor authenticationChanged, the latter being under a notification, seem to do anything when the home button is pressed.
Any help would be appreciated

Try subscribing to NSNoficationCenter to find out when your app goes to the background:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(userPressedHomeButton:)
name:UIApplicationDidEnterBackgroundNotification object:nil];
In your userPressedHomeButton: function you can decide how to notify the other player or suspend the game. BUT, you must take action quickly, because iOS will not allow your app to run more than a few seconds after it has been suspended.
As an alternate to subscribing to NSNotificationCenter, you can do your implementation in your AppDelegate:
- (void)applicationWillResignActive:(NSNotification *)notification { }

Related

Is There A Lost Focus Window Event in Objective C?

Coming from a .NET background I'm used to events getting fired so trapping a lost focus event is easy but I'm not sure how to do this in Obj-C. Basically I want my app to know when another application has gotten focus and it no longer has it so it can perform some actions.
Can you please tell me how I can implement this kind of functionality in Obj-C for an OSX app?
Have a look at the NSWindow notifications. Specifically, you're interested in NSWindowDidBecomeKeyNotification and NSWindowDidResignKeyNotification. You can also create a delegate for the window and implement its windowDidBecomeKey: and windowDidResignKey: methods, as noted in the NSWindowDelegate protocol documentation.
Or, if you just wanted to know when the application (not a window) has gained focus, you can subscribe to the NSApplicationDidBecomeActiveNotification. Likewise, NSApplicationDidResignActiveNotification will notify you when your app loses focus. These notifications are discussed more here. You can also implement applicationWillBecomeActive: and applicationWillResignActive: in the application delegate.
It's unclear if you want notification of a single window losing focus or notification of your entire app losing focus. My answer here provides notification for the entire application losing focus. (See mipadi's answer if you just want to know when one of your app's window loses focus.)
Observe the appropriate notification:
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:#selector(appDeactivated:)
name:NSWorkspaceDidDeactivateApplicationNotification
object:nil];
Then add the handler method:
-(void) appDeactivated:(NSNotification *)notification
{
NSRunningApplication* app = [notification.userInfo objectForKey:#"NSWorkspaceApplicationKey"];
if (app == [NSRunningApplication currentApplication]) {
// your cleanup code here
}
}

How to Display Skip Button to close the MPmoviePlayerViewController at 10 Secs of playing Video

In my app Im playing an video using MPmoviePlayerViewController.
actually some videos are too long to watch around 3-5 mins.
I want to allow user to SKIP the video after 10 seconds if he wants.
My requirement is
I need to display the count down 10, 9, 8 -- 0 after 10th secod of the the video we display a skip button.
_moviePlayerViewController = [[MPMoviePlayerViewController alloc] init ];
[_moviePlayerViewController.view setFrame:self.view.frame];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayerViewController.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:nil];
_moviePlayerViewController.moviePlayer.shouldAutoplay = YES;
[_moviePlayerViewController.moviePlayer setFullscreen:YES];
_moviePlayerViewController.moviePlayer.repeatMode = MPMovieRepeatModeNone;
_moviePlayerViewController.moviePlayer.controlStyle = MPMovieControlStyleNone;
_moviePlayerViewController.moviePlayer.scalingMode = MPMovieScalingModeNone;
_moviePlayerViewController.moviePlayer.contentURL =[NSURL fileURLWithPath:videoPath];
in this application we have play back option,
ie if the user quit the application he can resume the video from the point of going background.
in both the case (resume after come foreground, and just now started video)
the user should see a skip button when the video play time is 10 seconds.
Can any one help please
What the problem? Use dispatch_after for 5 seconds pause then inside dispatch block run one second timer to count seconds remaining
EDIT
Oh I'm sorry, you need just one NSTimer and seconds counter ivar to track how many seconds passed from the video start
For playback option you can use [_moviePlayerViewController.moviePlayer pause]; when going in background and can again resume play from where it was when again come to foreground.
In case if user quit application you can provide playback option also. You can manage a counter variable separately, which count for how seconds the video is playing. Store the value of this counter when user quit application, in short store the value when player stops playing. Now when you again come back to this view you can check the actual length of video and compare with the duration for which it has already played and play back.This can be tricky but the pause thing mentioned above did work.
EDIT: For hiding and displaying skip button after 10sec the counter solution is perfect.

Get EAAccessoryDidConnectNotification when app is in background (iOS)

In my 'viewDidLoad'in ViewController.m, I am registering to the NSNotificationCenter defaultCenter with 'EAAccessoryDidConnectNotification' and 'EAAccessoryDidDisconnectNotification'
When my app is active in foreground, I get the notification, and respond in accessoryDidConnect. all works OK.
But, when app is in background, how can I get such notification?
('EAAccessoryDidConnectNotification' and 'EAAccessoryDidDisconnectNotification')
[Code below]
Thanks a lot.
Dan
(void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(accessoryDidConnect:)
name:EAAccessoryDidConnectNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(accessoryDidDisconnect:)
name:EAAccessoryDidDisconnectNotification
object:nil];
[[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
}
According to the documentation, it's not possible:
If your app is suspended in the background when an accessory
notification arrives, that notification is put in a queue. When your
app begins running again (either in the foreground or background),
notifications in the queue are delivered to your app. Notifications
are also coalesced and filtered wherever possible to eliminate any
irrelevant events. For example, if an accessory was connected and
subsequently disconnected while your app was suspended, your app would
ultimately not receive any indication that such events took place.
But it would be interesting if someone proved me wrong.
in iOS 12.1.4, plug in the relay cable with iPhone and DSLR Camera when app is in foreground, then switch app into background mode, unplug the relay cable and switch app back into foreground, you will receive the accessoryDidDisconnect notify via EAAccessory's delegate methods.

How do you know when a user chooses to play a video through AirPlay?

I have a custom video player set up with custom controls, and I utilize MPVolumeView to provide an airplay button. When a user chooses to use AirPlay, they interact with that Apple UI and there is no event (that I can find) that says "hey, the video is now playing over AirPlay".
The problem is that, if I close the player and reopen it, it loads the movie (load state changes to MPMovieLoadStatePlayable), I play it, and I immediately get a playback did finish notification with reason being MPMovieFinishReasonPlaybackEnded, and the video continues to try to play through AirPlay. I'm certain the movie stops and is deallocated whenever I close the player.
If anyone has any advice on how to handle this, knows some events to listen for, or has any ideas about this whatsoever, please let me know. Thanks!
The answer here turns out to be that, at least up to 4.3, there is no way to get an answer to this through code.
The problem in this case is how you dispose of the MPMoviePlayerController when you're finished with it. Even if the video plays through, before you finally release it, you have to call pause and then stop. Like this:
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc] init];
// use the player. then when done with it:
[mp pause];
[mp stop];
[mp release];
If you don't do this then the next time you create a MPMoviePlayerController, certain properties are somehow ghosted in the framework. Playing a video progressively caused audio from the previous mp to play while the new mp did its initial buffering. Also, if the previous video was playing over airplay, the next video would get a notification that the video finished right after it starts and some other weirdness.
Long story short, dispose of your video players with the above sequence to avoid issues with later movie players.

Definitive answer to what playersToInvite is for

The Game Center documentation indicates that the
playersToInvite parameter is non-nil
when your application is launched
directly from the Game Center
application to host a match.
A few people have asked how this works exactly, i.e. there doesn't appear to be a way to select a friend from the Game Center application and invite them to play from Game Center; it only works when you invite in-game. Is this documentation dated or is there a secret way to start a game-specific match from Game Center? I'd like to test my inviteHandler but I've been unable to determine how this parameter is passed to the application.
[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite)
{
// clean up games in progress here
if (acceptedInvite)
{
NSLog(#"acceptedInvite %#", acceptedInvite);
// The acceptedInvite parameter is non-nil when the application receives an
// invitation directly from another player.
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
mmvc.matchmakerDelegate = self;
[self disableHomeUI];
[self presentModalViewController:mmvc animated:YES];
}
else if (playersToInvite)
{
NSLog(#"playersToInvite %#", playersToInvite);
// playersToInvite parameter is non-nil when your application is launched
// directly from the Game Center application to host a match
[self disableHomeUI];
[self doPresentMatchMakerUIWithPlayersToInvite:playersToInvite];
}
};
I think the docs do not reflect the current state of affairs. As far as I can tell, the Game Center App does not even offer an interface for inviting friends to play, currently.
Also, check the developer forums (apparently you have ;) ). Someone from Cupertino seems to think it is not possible. So...
After launching my application Cee-lo into production, the playersToInvite code became active. This seems to be because the Sandbox version of the Game Center app itself does not allow you to start a game with a player from there, but the production version does. Not a very good test environment if you ask me!
There is now a way to use the Game Center app to invite a Game Center friend. It ONLY works if your game calls registerListener: on the localPlayer GKPlayer:
Game Center App
-> games tab
-> your game
-> Players section
-> select a player
-> "Play a Game"
This will send a push notification invite to the other player. Game does not have to be running on either device. As of iOS7.
This flow also works:
Game Center App
-> friends tab
-> tap a friend
-> tap a game in common (your game)
-> tap the "..." in the top right corner
-> tap "Play"
I could be wrong, but i think it is just the "simulator" that can not invite particular friends to play.
I have been able to use 2 or more iPhones running in the sandbox to invite particular friends to play, and it has worked wonderfully for debugging the invite handler piece of code.
As another poster mentioned, there does not appear to be at this time a way of inviting particular friends to play a particular game from Game Center.
Happy gaming!