I'm working on a project in which, video will be played when a button is clicked. MPMoviePlayer worked fine before I use this button action. But after implementing that, Video plays fine but the player doesn't recognise touch and it doesn't even shows playback time. Only showing like this ( - - ).
I'm working on this code:
-(void) sceneBegins:(id)sender
{
....
theMoviePlayer = [MPMoviePlayerController new];
[theMoviePlayer setContentURL:movieURL];
theMoviePlayer.controlStyle = MPMovieControlStyleEmbedded;
theMoviePlayer.backgroundView.hidden = YES;
[theMoviePlayer setMovieSourceType:MPMovieSourceTypeFile];
theMoviePlayer.shouldAutoplay = YES;
[theMoviePlayer prepareToPlay];
[theMoviePlayer.view setFrame:View.bounds];
[theMoviePlayer.view setUserInteractionEnabled:YES];
theMoviePlayer.scalingMode = MPMovieScalingModeAspectFit;
[View addSubview:theMoviePlayer.view];
theMoviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[theMoviePlayer play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sceneChange:)
name:MPMoviePlayerPlaybackDidFinishNotification object:theMoviePlayer];
....
}
Also it doesn't enters in to the stop notification method when the video stops playing.
Try this line of code :-
[myButton addTarget:self action:#selector(dragEnded:withEvent: )
forControlEvents: UIControlEventTouchUpInside |
UIControlEventTouchUpOutside];
Related
I know possibly this is duplicate question but the question which is already exist didn't have an solution so , I'm asking again to possibly start bounty question .
Here is my code which is working below iOS 11 :
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// create a player view controller
avcontroller = [[AVPlayerViewController alloc]init];
avcontroller.player = player;
[player play];
NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
[noteCenter addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSLog(#"Video end");
self.avcontroller.player = nil;
[self.avcontroller.view removeFromSuperview];
[self.view addSubview:delegate.tabViewControllerObj.tabBarController.view];
}];
_skip =[UIButton buttonWithType:UIButtonTypeCustom];
[_skip addTarget:self action:#selector(btnSkipTapped)
forControlEvents:UIControlEventTouchUpInside];
[_skip setTitle:#"Skip" forState:UIControlStateNormal];
_skip.layer.borderWidth = 2.0f;
_skip.layer.cornerRadius = 12;
_skip.clipsToBounds = YES;
_skip.layer.borderColor = [UIColor whiteColor].CGColor;
// show the view controller
[self addChildViewController:avcontroller];
[avcontroller.view addSubview:_skip];
[avcontroller.view bringSubviewToFront:_skip];
[self.view addSubview:avcontroller.view];
avcontroller.view.frame = self.view.frame;
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
_skip.frame = CGRectMake((self.view.frame.size.width-140),(self.view.frame.size.height-150),100.0,35.0);
}
And here is button tapped function:
- (IBAction)btnSkipTapped{
NSLog(#"Skip button clicked");
self.avcontroller.player = nil;
[self.avcontroller.view removeFromSuperview];
[self.view addSubview:delegate.tabViewControllerObj.tabBarController.view];
}
This code will display button perfectly but upon button tap , it didn't call btnSkipTapped function.
Any help would be appreciated !
#DeepShah you have added skip button in avcontroller.view so its display proper but you can't click on it because AVPlayerViewControllerContentView covers that skip button.
see below image :
so you have to add skip button in self.view and its works.
[self.view addSubview:_skip];
[self.view bringSubviewToFront:_skip];
I have a problem while playing a video in full screen mode using MPMoviePlayerViewController (works perfectly in normal mode).
CODE:
if (PlayV) {
self.previewView.hidden=NO;
self.videoController =[[MPMoviePlayerController alloc] initWithContentURL:self.videoURL];
[self.videoController.view setFrame:self.previewView .frame];
self.videoController.view.center=self.playBtn.center;
[self.previewView addSubview:self.videoController.view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(videoPlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.videoController];
self.videoController.scalingMode = MPMovieScalingModeAspectFit;
self.videoController.controlStyle = MPMovieControlStyleNone;
[self.videoController play];
}
I got the solution. Add this line of code in playBtnAction method:
- (IBAction)playBtnAction:(id)sender {
[self.videoController setFullscreen:YES animated:YES];
}
and then add this line of code in your videoPlayBackDidFinish.
MPMoviePlayerController *player=[notification object];
if ([player respondsToSelector:#selector(setFullscreen:animated:)]) {
[player.view removeFromSuperview];
}
This code will check if the video is in fullscreen mode and bring it back to normal mode.
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:imagepath]]; //moviePlayer declared in .h and set URL
moviePlayer.view.frame = CGRectMake(364, 89, 660, 668); //set custom frame
moviePlayer.controlStyle = MPMovieControlStyleDefault;
moviePlayer.shouldAutoplay = YES;
[self.view addSubview:moviePlayer.view]; //add to view
[moviePlayer setFullscreen:NO animated:YES];
This may help you.
I am trying to figure out why I am getting a flash of black screen after I play a video through once. I figured out that when the load state is MPMovieLoadStatePlayable there is no black screen and the video plays through smoothly. However, after the video plays through once the load state becomes MPMovieLoadStateUnknown. I noticed that when the load state is unknown there is a flash of black screen, probably because it has to first call prepareToPlay.
Here is is how I am setting up my video:
- (void)setVideo:(PFObject *)aVideo {
video = aVideo;
if(self.moviePlayer) {
self.moviePlayer = nil;
}
// Get the profile image
PFUser *user = [self.video objectForKey:kFTPostUserKey];
PFFile *profilePictureSmall = [user objectForKey:kFTUserProfilePicSmallKey];
NSString *authorName = [user objectForKey:kFTUserDisplayNameKey];
// Get the video file
PFFile *videoFile = [video objectForKey:kFTPostVideoKey];
NSURL *url = [NSURL URLWithString:videoFile.url];
self.moviePlayer = [[MPMoviePlayerController alloc] init];
[self.moviePlayer.view setFrame:CGRectMake(0.0f,0.0f,320.0f,320.0f)];
[self.moviePlayer setControlStyle:MPMovieControlStyleNone];
[self.moviePlayer setScalingMode:MPMovieScalingModeAspectFill];
[self.moviePlayer setMovieSourceType:MPMovieSourceTypeFile];
[self.moviePlayer setContentURL:url];
[self.moviePlayer requestThumbnailImagesAtTimes:#[ #0.1f, #1.0f ] timeOption:MPMovieTimeOptionExact];
[self.moviePlayer setShouldAutoplay:NO];
[self.moviePlayer.view setBackgroundColor:[UIColor clearColor]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallBack)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerStateChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(loadStateDidChange:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.moviePlayer];
}
Here are the functions:
- (void)didTapVideoPlayButtonAction:(UIButton *)sender{
[self.playButton setHidden:YES];
[self.moviePlayer prepareToPlay];
[self.moviePlayer requestThumbnailImagesAtTimes:#[ #0.1f, #1.0f ] timeOption:MPMovieTimeOptionExact];
[self.moviePlayer play];
}
-(void)movieFinishedCallBack{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
}
-(void)loadStateDidChange:(NSNotification *)notification{
//NSLog(#"loadStateDidChange: %#",notification);
if (self.moviePlayer.loadState == MPMovieLoadStatePlayable) {
NSLog(#"loadState... MPMovieLoadStatePlayable");
}
if (self.moviePlayer.loadState == MPMovieLoadStatePlaythroughOK) {
NSLog(#"loadState... MPMovieLoadStatePlaythroughOK");
}
if (self.moviePlayer.loadState == MPMovieLoadStateStalled) {
NSLog(#"loadState... MPMovieLoadStateStalled");
}
if (self.moviePlayer.loadState == MPMovieLoadStateUnknown) {
NSLog(#"loadState... MPMovieLoadStateUnknown");
//[self.moviePlayer prepareToPlay];
}
}
-(void)moviePlayerStateChange:(NSNotification *)notification{
//NSLog(#"moviePlayerStateChange: %#",notification);
if (self.moviePlayer.playbackState == MPMoviePlaybackStatePlaying){
[self.imageView addSubview:self.moviePlayer.view];
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStateStopped){
NSLog(#"moviePlayer... Stopped");
[self.playButton setHidden:NO];
//[self.moviePlayer.view removeFromSuperview];
[self.moviePlayer prepareToPlay];
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStatePaused){
NSLog(#"moviePlayer... Paused");
[self.moviePlayer stop];
}
f (self.moviePlayer.playbackState == MPMoviePlaybackStateInterrupted){
NSLog(#"moviePlayer... Interrupted");
[self.moviePlayer stop];
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStateSeekingForward){
NSLog(#"moviePlayer... Forward");
}
if (self.moviePlayer.playbackState == MPMoviePlaybackStateSeekingBackward){
NSLog(#"moviePlayer... Backward");
}
}
I think that the solution would be, calling prepareToPlay from within the statement:
if (self.moviePlayer.loadState == MPMovieLoadStateUnknown)
I tried this but it did not prepare the player for play. Any thoughts/advice/help?
The fact that the video can play once but then can't play again later is not some built-in feature of MPMoviePlayerController — I've never had an MPMoviePlayerController of mine behave like that — so you should look for something else that might be happening so as to wreck the state of your MPMoviePlayerController, such as changing its contentURL to a bad value (which is usually the cause of MPLoadStateUnknown. Two things come to mind:
I notice that the method where you configure your MPMoviePlayerController is no ordinary method; it is, in fact, a setter for a property (video). This could be involved in the problem, because it means that every time any code anywhere says video = //... you are running this method, which means tearing down the entire movie player and making a new one. Now suppose some code somewhere else says video = nil or some other bad value. That would certainly make your movie player view go black and prevent further playing. I suggest breakpointing this method to see if that's happening. And then set up a better architecture: A setter should just set the property and no more. The configuration of your movie player should happen just once and needs to happen in a method of its own.
Watch out for a situation where you accidentally generate more than on MPMoviePlayerController. There is a law that "There Can Be Only One" - if another MPMoviePlayerController comes along and calls prepareToPlay, all other MPMoviePlayerControllers are disabled.
(Finally, although this is not the direct source of your problem, note that you are determining the load state incorrectly. You are using equality, but this can easily fail, because the load state is a bit mask; you have to use logical-and to compare masks.)
i am just playing a video by using MPMoviePlayerController...my code is
-(void)playMovie:(NSURL *)url
{
moviePlayer =
[[MPMoviePlayerController alloc]
initWithContentURL:url];
if (IDIOM==IPAD) {
[moviePlayer.view setFrame:CGRectMake(22,100, 720, 300)];
}
else
{
(IS_IPHONE_5)? [moviePlayer.view setFrame:CGRectMake(22, 70, 280, 150)]:[moviePlayer.view setFrame:CGRectMake(22, 40, 260, 140)];
}
[_scrollView addSubview:moviePlayer.view];
moviePlayer.scalingMode =MPMovieScalingModeFill;
[moviePlayer prepareToPlay];
[moviePlayer play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidEnterFullscreen:) name:MPMoviePlayerDidEnterFullscreenNotification object:Nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidExitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:Nil];
}
-(void)moviePlayerDidEnterFullscreen :(id)sender
{
NSLog(#"fullscreen");
[moviePlayer play];
moviePlayer.scalingMode =MPMovieScalingModeFill;
}
- (void) moviePlayerDidExitFullScreen:(id)sender {
NSLog(#"exit full screen");
[moviePlayer play];
moviePlayer.scalingMode =MPMovieScalingModeFill;
}
here when i play initially video will be in "MPMovieScalingModeFill" mode...but my problem is that if i press full screen it shows video on full screen ..when i press exit "full screen" then my video mode goes to "MPMovieScalingModeAspectFit" mode.but i need to be always in "MPMovieScalingModeFill" mode .whats wrong with my code..Please help me...
I believe this will generate the MPMoviePlayerScalingModeDidChangeNotification.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieScalingModeDidChange:)
name:MPMoviePlayerScalingModeDidChangeNotification
object:nil];
Source :Apple Doc
MPMoviePlayerScalingModeDidChangeNotification
Posted when the scaling mode of a movie player has changed. There is no userInfo dictionary.
Scaling mode can change programmatically or by user interaction. To set or retrieve the scaling mode of a movie player, access its scalingMode property. The movie player whose state has changed is available as the object associated with the notification.
First set the ScalingMode to None and then set the ScalingMode to AspectFill
Swift Code :
NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayerExitFullscreen:", name: MPMoviePlayerDidExitFullscreenNotification, object: self.moviePlayer)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "moviePlayerEnterFullscreen:", name: MPMoviePlayerWillEnterFullscreenNotification, object: self.moviePlayer)
func moviePlayerEnterFullscreen (notification : NSNotification)
{
self.moviePlayer.scalingMode = MPMovieScalingMode.None
self.moviePlayer.scalingMode = MPMovieScalingMode.AspectFill
}
func moviePlayerExitFullscreen (notification : NSNotification)
{
self.moviePlayer.scalingMode = MPMovieScalingMode.None
self.moviePlayer.scalingMode = MPMovieScalingMode.AspectFill
}
This isn't the "ideal" solution, but it works! Basically, once you exit full screen the MPMoviePlayerController instance gets all screwed up and resetting the scaling property to MPMovieScalingModeFill won't help no matter where or when you do it (I've tried all sorts of stuff and after an hour gave up). Easiest solution is to remove the MPMoviePlayerController and simply allocate a new instance of MPMoviePlayerController each time full screen is exited (not ideal, but totally works):
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:NO];
if (self.moviePlayer != nil)
[self.moviePlayer.view removeFromSuperview];
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:self.videoURL];
self.moviePlayer.view.frame = CGRectMake(#, #, #, #);
self.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
self.moviePlayer.shouldAutoplay = NO;
[self.moviePlayer setContentURL:self.videoURL];
[self.moviePlayer prepareToPlay];
[self.moviePlayer setScalingMode:MPMovieScalingModeFill];
[self.view addSubview:self.moviePlayer.view];
}
PS: Don't forget to call super on viewDidAppear or suffer all sorts of unforeseeable mayhem (a very common mistake in iOS development)
I am developing an iPad app where I am playing the videos stored within the app itself. I am representing the list of videos in a table view. When I select a row, the video
corresponding to that row plays. But while performing this, sometimes screen goes black , no video is visible but only audio is playing.
I am aware that making the video play in fullscreen mode or using the MPMoviePlayerViewController eliminates this problem. But my requirement is that I don't want to play the movie in fullscreen initially. Please guide me on how this can be achieved.
-(void)playMovie {
MPMoviePlayerController *movieController = [[MPMoviePlayerController alloc] initWithContentURL:movieUrl];
self.moviePalyer = movieController;
[movieController release];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePalyerDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object: self.moviePalyer];
self.moviePalyer.view.frame = CGRectMake(240, 0, 561, 313);
self.moviePalyer.view.backgroundColor = [UIColor clearColor];
[self.moviePalyer prepareToPlay];
[self.view addSubview: self.moviePalyer.view];
[self.moviePalyer play];
}
-(void)moviePalyerDidFinish:(NSNotification*)notification
{
[moviePalyer.view removeFromSuperview];
[moviePalyer stop];
moviePalyer.initialPlaybackTime = -1.0;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePalyer];
[moviePalyer release];
moviePalyer = nil;
}
NOTE: This is on ipad simulator
I have solved the issue. Previously I was creating the MPMoviePlayerController for each of the row selection, and releasing it in the moviedidfinish notification method .But now, instead of creating movieplayercontroller for every row selection, I am reusing the MPMoviePlayerControler object which has been already created.
Following is the Code snippet:
-(void)playMovie
{
if(self.moviePalyer == nil)
{
MPMoviePlayerController *movieController = [[MPMoviePlayerController alloc] initWithContentURL:url];
self.moviePalyer = movieController;
[movieController release];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePalyerDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePalyer];
self.moviePalyer.repeatMode = MPMovieRepeatModeOne;
self.moviePalyer.view.frame = CGRectMake(240, 0, 561, 313);
self.moviePalyer.view.backgroundColor = [UIColor clearColor];
}
else
{
[self.moviePalyer setContentURL:url];
[self stopMovie];
}
[self.view addSubview: self.moviePalyer.view];
[self.moviePalyer play];
}
-(void)stopMovie
{
[self.moviePalyer.view removeFromSuperview];
[self.moviePalyer stop];
self.moviePalyer.initialPlaybackTime = -1.0;
}
I am releasing the moviePlayer object in the dealloc method.
Hope this helps who is having the same issue.