iOS presentMoviePlayerViewControllerAnimated can't be called twice using the same viewController - iphone

So I'm trying to present a MPMoviePlayerViewController using the method presentMoviePlayerViewControllerAnimated in my own view controller.
However, once I clicked the blue Done button on the top left, when I present the same viewController again (so that I can resume a video without having to create another instance of MPMoviePlayerViewController), the controls will no longer work if you let them disappear on their own after a few seconds. The controls will still function if you interact with them before they disappear, but once they fade away on their own, you can no longer bring them back up when tapping the video. This happens on both the device and the simulator.
Simplified code:
- (void) startPlayback
{
if (self.videoViewController == nil)
{
self.videoViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:self.videoUrl]];
}
// present the video player
[self presentMoviePlayerViewControllerAnimated:self.videoViewController];
}
assume that startPlayback is a delegate method or something in a view controller, and it's being triggered by a button. Self would refer to the view controller in this case.
So with this, it will bring up the video player which works perfectly. Then, once I wait a bit, the controls will disappear and I can bring them back by tapping the video. I can then dismiss this video player using the Done button on the top left. Once I dismiss it, and I can then bring back the video view controller. The video will still be playing, but now, when I wait a bit and the controls disappear, I can no longer bring up the controls by tapping the screen, effectively trapping myself in the video player.
I have found various solutions into hooking into the Done button, but it hasn't really allowed me to reuse the video player. For example:
// Remove the observer so that the blue button doesn't close the viewController
[[NSNotificationCenter defaultCenter] removeObserver:self.videoViewController name:MPMoviePlayerPlaybackDidFinishNotification object:self.videoViewController.moviePlayer];
// Add itself as an observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieEnded:) name:MPMoviePlayerPlaybackDidFinishNotification
object:self.videoViewController.moviePlayer];
In my movieEnded:, I can then dismiss the movie view controller via:
[self dismissMoviePlayerViewControllerAnimated];
But when I try to present the viewController again, the video player just gets stuck Loading... forever.
Any ideas?

Related

Having a Movie as a transition between two View Controllers - where to put this code?

My whole goal is to have a button on the main view, when you press this button a video plays and when the video is done playing you're now at the second view. The quick video is like a transition between the two VCs. My question is where should I put the 'play movie' code. Here are the scenarios I've tried and the unsatisfying outcomes:
The button in Main VC plays the movie and opens second VC - The movie plays but the second view controller doesn't open, just goes back to the main VC.
The button in Main VC plays the movie and the NSNotification for moviePlayBackDidFinish opens the second VC - same result as above.
The button in Main VC switches to second VC and movie code is in second VC's viewDidLoad (also viewWillLoad, same result) - VC switches but movie doesn't play
The button in Main VC switches to second VC and movie code is in second VC's viewDidAppear - second VC appears then movie plays continuously (not what I want).
What is the best way to set up the code to get the transition effect I'm looking for? Should I make a third View Controller in between the two just to play the movie? Here is the code I'm using to play the movie:
//Sets up the movie file to play
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"TransitionMovie" ofType:#"mov"]];
_moviePlayer = [[MPMoviePlayerViewController alloc]
initWithContentURL:url];
//Creates notification observer so it knows when the movie is done playing
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayer];
//Plays the movie
[self presentMoviePlayerViewControllerAnimated:_moviePlayer];

Playing subsequent movies in one MPMoviePlayerViewController

I am having a difficulty with the MPMoviePlayViewController.
I insatiate the controller, assign the url and show the player using:
[self presentMoviePlayerViewControllerAnimated:[appDelegate movieController]];
Then when the movie finished I dismiss it:
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self dismissMoviePlayerViewControllerAnimated];
The movie player is alloc in my AppDelegate.
There are some other listeners on MPMoviePlayerPlaybackDidFinishNotification. This is for the case where there might e.g. only be audio and it shows a play/pause button and counters in table cells.
The problem is that when I load a second movie in the same MPMovieViewController, it appears fine but the controls are not working correctly. They are work as long as they are visible, but as soon as they disappear there is no may of getting them back and therefore to dismiss the movie player.Sometimes closing and opening the App works, but sometimes it doesn't and I need to 'kill' the App in order to be able to start again.
Is there a way to play subsequent video's in the MoviePlayer while the controls still work?
Any suggestions how to 'reset' the Player in a way that I can prevent the other listeners from given a DEALLOC as they are listening for the action?
you dont need to dismiss the player you just need to set the new url... or maybe I missunderstood your problem...
Try adding this to your setup movie player controller
moviePlayerController.view.userInteractionEnabled = YES;

Control done button

I have a view with some objects, one of them is a webview where I play a video, this view change the size and the position of the object when the device rotates. The problem occurs when I am playing the video in full screen, if I start watching the video in landscape and while I am watching the video (full screen) I rotate the device and then I hit the done button when I return to the view the objects are not in the position that they should be in that orientation.
I set the position in a function, I call that function in viewdidload and also in willAnimateRotationToInterfaceOrientation but how can I control the rotation while I am watching the video?
You could do something like this:
-(void) viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerPlaybackDidFinish:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
}
- (void) playerPlaybackDidFinish:(NSNotification*)notification
{
[self resizeSubviews];
}
So, when the playback finishes, you call your method to resize your subviews, and by the time the player closes, your view should look correct for the orientation.
You could also register for MPMoviePlayerWillExitFullscreenNotification instead, if that more properly fits your needs.

How to play video in iphone landscape mode?

I have one application in which list of videos that are coming through xml parsing are displayed in tableview. When I click particular video it should be played in landscape mode.
For that I followed tutorial:
http://iosdevelopertips.com/video/how-to-play-movies-from-application-bundle-or-from-a-remote-server-url.html
It works perfectly but it uses separate modalcontroller so when I press done button on the video or completed video is completed it returns to the that modal view and on which
back button appears and when I press that back button after that I can go back to list of videos screen.but I want to go directly back to the screen which displays list of videos.
for that if i write code using pushviewcontroller than application crashes.How can i solve this problem.any tutorial or sample code?
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
[self dismissModalViewControllerAnimated:YES];
DonationVideoViewController *dvvc=[[DonationVideoViewController alloc] initWithNibName:"DonationVideoViewController" bundle:nil];
[self.navigationController pushViewController:dvvc animated:YES];
}
UPDATE:I have solved the issue by using the code for calling custommovieplayercontroller in the same class where I have displayed the list of videos. So now video ends it remains to the page I want and I need to go to other page using pushviewcontroller
You should probably push dvvc in viewDidDisappear. But like Till says, we need to see the error message you are getting.

When I press "DONE" while playing movie using MPMoviePlayerController which view will get displayed

I am playing movie using MPMoviePlayerController,
I am using TableView,what happening with my application is when I press accessory button it will display detailed view and when I press cell area it will play movie that I wanted,(the way youtube application does)
but when I press "DONE" while playin movie it'll navigate to a view which is not my detail view but some empty view.
Any idea what should I do to achieve it so that when user press "DONE" it will nevigate me to my detail view instead of some empty view.
I tried to push view when "movieFinishedCallback" is executed but it'll pushing one more view on that empty view.
Ideally if your code is correct, pressing the Done button on MPMoviePlayerController object would close the MPMOviePlayerController and return to the controller which invoked it (which in your case is the detail view)
You do not need to do anything in the movieDidFinishCallback except maybe release the movieplayer object.
-(void)myMovieFinishedCallback:(NSNotification*)aNotification {
MPMoviePlayerController* theMovie = [aNotification object];
theMovie.initialPlaybackTime = -1.0;
}