How to tell if MoviePlayerController has ever played? - ios

I want to prevent a user from performing an action until they have at least pressed play on the MoviePlayerController. Would also be helpful to know if they have watched the video all the way through, or how far they have watched.

At some point register for a playback notification like so:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackStateChanged)
name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
Then, within playbackStateChanged, you can indicate that you have played the video with some BOOL:
- (void) playbackStateChanged {
if(moviePlayerController.playbackState == MPMoviePlaybackStatePlaying){
hasPlayed = YES; //BOOL value
}// reading the playback
}

You can set a variable called countOfTimesButtons. You can have an IBAction on the play button and when it is clicked, you can increase the countOfTimesButtons pressed. If the countOfTimesButtons is greater than 0, you can do something depending on your circumstance.
Hope this helps...

you can also save the state in a persistent way, so the user will not have to view the video at each application session:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"videoViewed"];
and elswhere in the program:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"videoViewed"]) {
do stuff
}

Related

How to call method/code when app is paused in iOS

As the title reads; I am currently playing a sound file on loop using this code:
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"smoothjazz" ofType:#".mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:soundFilePath])
{
// Your code to play the sound file
[player setVolume:1.0];
player.numberOfLoops = 5; //infinite
[player play];
}
However, the music keeps playing when you pause the app (hit the home button). How can I call [player setVolume:0.0] when the app is paused and [player setVolume:1.0] when it is resumed?
All help appreciated.
You can use NSNotificationCenter to listen to the UIApplicationWillResignActiveNotification and UIApplicationDidBecomeActiveNotification notifications in your view controller (or whatever object your above code is in) and the pause/resume playing you sounds there.
You should probably not set the volume on your player. It would probably be better to call
[player pause] and [player play]
There is a protocol that handles state change: UIApplicationDelegate. The ones you are interested in right now are willResignActive and didBecomeActive.
Note that these are not didEnterBackground and willEnterForeground. The difference is the former will get hit when apps takeover, such as Siri, and the latter will not.
You can implement this protocol in your audio manager class and set the volume at that point, like so:
- (void)applicationWillResignActive:(UIApplication *)application {
self.currentVolume = self.player.volume;
self.player.volume = 0;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
self.player.volume = self.currentVolume;
}
There may be no need to store the current volume, but designing on it to be used like that now will allow you to implement that in the future.
You should consider whether or not you want to mute the player or pause it. I'm sure you have, but a general better practice here would be to pause it rather that mute it, but that's not something that applies to every situation.
Additionally, you should know that some programmers are of the school of thought that only the AppDelegate should implement the UIApplicationDelegate protocol. There's some good arguments for it, and personally, I'm not really decided on what's best practice on that, but if you want to follow that, then you can either set up a protocol to delegate these in your AppDelegate and have your audio manager implement that delegate or you can use NSNotificationCenter to broadcast the event to any listeners - so, your audio manager in this case. Of the two, I would say using notifications is a cleaner way to handle it (delegating to delegates is a bit silly to me), but they also can get messy if you're not careful.
Here's the code I added to the viewDidLoad to call the method on the app pausing:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(muteMusic)
name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(activateMusic)
name:UIApplicationDidBecomeActiveNotification object:nil];
Then, of course, my two methods:
- (void) muteMusic {
[player pause];
}
- (void) activateMusic {
[player play];
}
Enjoy!

How to play audio at launch image in Cocos2D v3.x iOS?

I'm making a game in Cocos2D iOS and would like play a short audio clip (in .m4a format) when the launch image (Default) is displayed.
I tried adding this line:
[[OALSimpleAudio sharedInstance] playBg:#"clip.m4a"];
in application didFinishLaunchingWithOptions but doesn't work.
I also tried playing a .caf file instead of .m4a, but it also doesn't play.
Can you guys please help me in this regard?
Thanks a lot!
Are you talking about the default loading screen that is defined in your project settings as 'default.png'? If yes, I don't think it's possible to play a sound at the same moment the app is launched, because it is currently loading it. What you could do however is a IntroScene that would only implement the onEnter method and immediately apply a transition to, example, your Main Menu. This is what I am doing right now in my game (using cocos2D 2.1, but I guess this isn't very different from a version to another) :
-(void) onEnter
{
[super onEnter];
CCScene *scene;
//Check if app has already launched once
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"]) {
scene = [MainMenuScene sceneWithParticles:nil];
}else{
scene = [Tutorial sceneWithParticle:nil];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
//PLAY YOUR SOUND HERE
//Transition
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:scene]];
}
Hope this helps! :)

MPMoviePlayerController seek forward button stops the video in IOS7?

I am facing an issue with MPMoviePlayerController in iOS 7. When i single tap on the forward seek button the video stops and not allow to do anything like to play again full screen and slider change.
Here is my code.
remove the Observer for the MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter] removeObserver:moviePlayerViewController name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerViewController.moviePlayer];
and add New Notification MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
Here is my custom method to handle the MPMoviePlayerPlaybackDidFinishNotification
-(void)videoFinished:(NSNotification*)aNotification{
MPMoviePlayerController *moviePlayer = [aNotification object];
NSLog(#"%f",moviePlayer.currentPlaybackTime);
int reason = [[[aNotification userInfo] valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (reason == MPMovieFinishReasonPlaybackEnded) {
}else if (reason == MPMovieFinishReasonUserExited) {
[self performSelector:#selector(dismiss:) withObject:aNotification afterDelay:0.5];
}else if (reason == MPMovieFinishReasonPlaybackError) {
}
}
I need to stop this strange behaviour on single click and continue to play.
Anyone know how to do this?
Thanks.
I think there are no any notifications or event are available on user
interaction with the standard player buttons, and i have to implement
own UI for the player controls. by this way we can then determine the
actions for a single touch, long touch, etc. Then, we can add whatever
functionality like increasing the play rate, or simply seeking to a
time.

Send NSNotification from AppDelegate

I want to send an NSNotification from this method (when the UIButton is clicked) in my AppDelegate.m:
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
//cancel clicked ...do your action
// HERE
}
}
..and receive it in one of my UIViewControllers. How can I do that?
EDIT WITH MORE INFO: I am making an alarm app, and when the user presses the UIButton, I want to stop the alarm. I figured that NSNotifications is the only way to get information from my AppDelegate.m file to a ViewController.m file?
You should to register your receiver object to accept some messages sent from Notification Center.
Suppose you have Obj A which controls your alarm, and value "stopAlarm" is the message which can stop alarm. You should create an observer for a "stopAlarm" message.
You can do, with:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(controller:)
name:#"stopAlarm"
object:nil];
Now, you should create a method controller that manages this messages:
- (void)controller:(NSNotification *) notification {
if ([[notification name] isEqualToString:#"stopAlarm"]){
//Perform stop alarm with A object
}
}
Finally, you can send the message "stopAlarm" when you want in the code with:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"stopAlarm"
object:nil];
I Hope this may help.
EDIT:
When your UIViewController are unloaded or when app terminate, you should call:
[[NSNotificationCenter defaultCenter] removeObserver:self];
for stop observing.
That's all.
Thanks to Hot licks for correction.
You may want to create a class–maybe even a singleton if there is only one alarm–that manages the timer. That way you can manage from any place in your application rather than in the view controller. Take a look at:
http://dadabeatnik.wordpress.com/2013/07/28/objective-c-singletons-an-alternative-pattern/
and:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Notifications/Articles/NotificationCenters.html
As Hot Licks mentioned, you really do not want to jump into this without knowing what is going on. Hopefully these links will help get you going in the right direction.

How to stop MPMoviePlayerViewController's automatic dismiss on moviePlaybackDidFinish?

An MPMoviePlayerViewController which is presented modally through presentMoviePlayerViewControllerAnimated: automatically dismisses itself when it's content finishes playing.
I've tried to disable this, since I want to play other content afterwards. However, even if I register to the NSNotificationCenter with [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedCallback:) name:MPMoviePlayerPlaybackDidFinishNotification object:playerVC.moviePlayer]; and set some other content, it still dismisses.
How can I stop MPMoviePlayerViewController from automatically dismissing itself?
UPDATE:
As a clarification, this question is only about removing the automatic dismissal and not about dealing with the disabled 'done' button. The selected answer reflects. This is by design, since we assume the developer adds their own means of dismissing the MPMoviePlayerViewController. However, #bickster's answer deals with the 'done' button as well.
Thanks to this blog article I figured out that MPMoviePlayerViewController automatically registers itself to the NSNotificationCenter upon creation. You have to first remove this registration and it will stop dismissing itself automatically.
// Initialize the movie player view controller with a video URL string
MPMoviePlayerViewController *playerVC = [[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:aVideoUrl]] autorelease];
// Remove the movie player view controller from the "playback did finish" notification observers
[[NSNotificationCenter defaultCenter] removeObserver:playerVC name:MPMoviePlayerPlaybackDidFinishNotification object:playerVC.moviePlayer];
You can use this code to stop the viewcontroller from automatically dismissing and capture the event when the user clicks the "Done" button so you can dismiss the viewcontroller yourself.
Step 1. - alloc a MPMoviePlayerViewController
videoPlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:[[NSURL alloc ]initWithString:[aURL];
Step 2. - Remove the default MPMoviePlayerPlaybackDidFinishNotification observer and add your own
[[NSNotificationCenter defaultCenter] removeObserver:videoPlayer
name:MPMoviePlayerPlaybackDidFinishNotification object:videoPlayer.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:videoPlayer.moviePlayer];
Step 3. - Present viewcontroler
[self presentMoviePlayerViewControllerAnimated:videoPlayer];
Step 4. - Add videoFinish: method
-(void)videoFinished:(NSNotification*)aNotification{
int value = [[aNotification.userInfo valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (value == MPMovieFinishReasonUserExited) {
[self dismissMoviePlayerViewControllerAnimated];
}
}
You can try something like this.
when the mpmovieplayercontroller finishes playing a video and you recieve the notification in your method movieFinishedCallback: implemect
[playerVC.movieplayer setContentURL:// set the url of the file you want to play here];
[playerVC.moviePlayer play];
Hope this helps
Since "Done" button is not working anymore if I remove MPMoviePlayerPlaybackDidFinishNotification from NSNotificationCenter, I change repeat mode to MPMovieRepeatModeOne.
Then, everything's working fine except the video is repeated.
MPMoviePlayerViewController *playerVC = [[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:aVideoUrl]] autorelease];
[playerVC.moviePlayer setRepeatMode:MPMovieRepeatModeOne];

Resources