I have an app that plays local videos using the AVPlayerViewController.
But when the video has finished playing I want it to close automatically (like the MPMoviePlayerViewController used to do).
After posting this question, I managed to solve this partially thanks to the answers below and partially from Apples "Guides and Sample code".
This is the code that worked for me:
#import "ViewController.h"
#import AVFoundation;
#import AVKit;
#interface ViewController ()
#property(nonatomic, readonly) AVPlayerItem *currentItem;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)playerItemDidReachEnd:(NSNotification *) notification {
//remove the player
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)playVideo:(id)sender {
// grab a local URL to our video
NSURL *videoURL = [[NSBundle mainBundle]URLForResource:#"bagare" withExtension:#"mp4"];
// create an AVPlayer
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// create a player view controller
AVPlayerViewController *controller = [[AVPlayerViewController alloc]init];
controller.player = player;
[player play];
[self presentViewController:controller animated:YES completion:nil];
// show the view controller
controller.view.frame = self.view.frame;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:_currentItem];
}
#end
NSURL *url=[NSURL URLWithString:#"URLLINK"];
AVAsset *avAsset = [AVAsset assetWithURL:url];
AVPlayerItem *playerItem = [[AVPlayerItem alloc]initWithAsset:avAsset];
Subscribe to the AVPlayerItem's DidPlayToEndTime notification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
Pass the AVPlayerItem to a new player
AVPlayer *player = [AVPlayer playerWithURL:videoURL]
AVPlayerViewController *controller=[[AVPlayerViewController alloc]init];
controller.player=player;
[player play];
[self presentViewController:controller animated:YES completion:nil];
Here remove Player dismiss or Player added view
-(void)itemDidFinishPlaying:(NSNotification *) notification {
[self dismissViewControllerAnimated:YES completion:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
}
This should work:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(videoDidFinish:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[controller.player currentItem]];
- (void)videoDidFinish:(id)notification
{
AVPlayerItem *p = [notification object];
//do something with player if you want
[[NSNotificationCenter defaultCenter] removeObserver:self];
//fade out / remove subview
}
In .h file
#property(nonatomic, strong)AVPlayerViewController *controller;
In .m file:
- (IBAction)playVideo:(id)sender {
// grab a local URL to our video
NSURL *videoURL = [[NSBundle mainBundle]URLForResource:#"bagare" withExtension:#"mp4"];
// create an AVPlayer
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// create a player view controller
self.controller = [[AVPlayerViewController alloc]init];
controller.player = player;
[player play];
[self presentViewController:controller animated:YES completion:nil];
// show the view controller
controller.view.frame = self.view.frame;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:_currentItem];
}
And for dismiss:
- (void)playerItemDidReachEnd:(NSNotification *)notification {
[self.controller dismissViewControllerAnimated:YES completion:nil];
}
Related
I have implemented avplayer programatically.
#interface showAskUsVideo ()
{
AVURLAsset *asset;
AVPlayerItem *item;
}
#property (strong, nonatomic) AVPlayer *player;
-(void)viewWillAppear:(BOOL)animated
{
[self playVideo];
}
-(void)playVideo {
[playerViewController.view setFrame:CGRectMake(37, 80 ,495,220)];
asset = [AVURLAsset assetWithURL: url];
item = [AVPlayerItem playerItemWithAsset: asset];
_player = [[AVPlayer alloc] initWithPlayerItem: item];
playerViewController.showsPlaybackControls = NO;
playerViewController.player = _player;
[item addObserver:self forKeyPath:#"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:nil];
[_player addObserver:self forKeyPath:#"rate" options:0 context:nil];
[self.view addSubview:playerViewController.view];
}
But when I select deployment target 10.0 then its working fine. But for iOS 8.0 to 9.3 only PlaybackControls is seen on screen not video.
What need to change in my code?
Is playerViewController part of the view controller hierarchy? If not, that could explain it. Try adding it as a child view controller of your view controller:
[self addChildViewController:playerViewController];
[self.view addSubview:playerViewController.view];
Try like that: Add to .m
#property (nonatomic, retain)AVPlayer *player;
#property (weak, nonatomic) IBOutlet AVPlayerClass *playerView;
(playerView is your view where you want to show it)
NSURL *url = [[NSBundle mainBundle]URLForResource:#"video_name" withExtension:#"mp4"];
_player = [AVPlayer playerWithURL:url];
playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
playerLayer.frame = _playerView.bounds;
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[_playerView.layer insertSublayer:playerLayer atIndex:0];
_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_player currentItem]];
[_player play];
-(void)playerItemDidReachEnd:(NSNotification *)notification{
AVPlayerItem *p = [notification object];
[p seekToTime:kCMTimeZero];
}
If you using a ViewController for your player. The best practice is presentingViewController
[self presentViewController:playerViewController animated:YES completion:nil];
if you using xib
PlayerViewController *vc = [[PlayerViewController alloc]
initWithNibName:#"PlayerViewController" bundle:nil];
[self.view addSubview:[vc view]];
I have a MPMoviePlayerViewController. That ViewController always dismisses in an animated fashion. I want to dismiss it in 'NO animated' fashion. How can I do that?
NSURL *url = [NSURL fileURLWithPath:filePath];
moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self presentViewController:moviePlayer animated:NO completion:nil];
[moviePlayer.moviePlayer play];
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
[moviePlayer.moviePlayer stop];
[self dismissViewControllerAnimated:NO completion:nil];
}
Currently, from what I have tried, all dismissings are in an animated fashion and I don't know why.
Is there a way to add video to a view like you would with an image and an image view? I don't want the full screen mode like in the YouTube app.
You can use AVPlayer from AVFoundation Framework
AVPlayer Demo
Try this code.
1.Import media player framework- #import
2.Declare Instance variable MPMoviePlayerController *player;
-(void)viewDidLoad
{
//you can try other api to get movie file path in ios 8
NSString *url = [[NSBundle mainBundle]
pathForResource:#"Trailer"
ofType:#"m4v"];
player = [[MPMoviePlayerController alloc]
initWithContentURL:[NSURL fileURLWithPath:url]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
//—set the size of the movie view and then add it to the View window—
player.view.frame = CGRectMake(10, 10, 300, 300);
[self.view addSubview:player.view];
//—play movie—
[player play];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
//—called when the movie is done playing—
- (void) movieFinishedCallback:(NSNotification*) aNotification {
MPMoviePlayerController *moviePlayer = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
[moviePlayer.view removeFromSuperview];
}
//-(NSString *)path
//{
// NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, //NSUserDomainMask, YES);
// NSString *documentDir=[paths objectAtIndex:0];
// return [documentDir stringByAppendingPathComponent:#"Trailer.m4v"];
//}
The problem video can be seen in :
http://app.bowerchat.com/images/118_1435046739658.mp4
MPMoviePlayerViewController Dismissing immediately without play.
What can be reason?Some videos are loaded nicely and playing.
How can i check the video can be played or not?
I tried
NSLog(#"%lu",(unsigned long)self.mpController.moviePlayer.loadState);
NSLog(#"%d",self.mpController.moviePlayer == nil);
Results always 0 - 0
MY Code to play video
self.mpController = [[MPMoviePlayerViewController alloc] initWithContentURL:moveUrl];
[self.mpController.moviePlayer prepareToPlay];
NSLog(#"%lu",(unsigned long)self.mpController.moviePlayer.loadState);
NSLog(#"%d",self.mpController.moviePlayer == nil);
[parent presentMoviePlayerViewControllerAnimated:self.mpController];
The reason could be that movie that has extention *.mp4 is actually of different type.
Also try to add the following:
self.mpController.moviePlayer.shouldAutoplay = YES;
[self.mpController.moviePlayer play];
Try this snippet :
-(void)setupMovie
{
NSURL *movieURL = [NSURL fileURLWithPath:movieURL];
self.mpController = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
self. mpController.scalingMode = MPMovieScalingModeAspectFill;
self. mpController.controlStyle = MPMovieControlStyleNone;
self.mpController.view.frame = self.view.frame;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerPlaybackStateDidChange:) name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification object:nil];
[self.view addSubview:self.mpController.view];
[self.mpController prepareToPlay];
}
- (void)moviePlayBackDidFinish:(MPMoviePlayerController *)player
{
[self.mpController.view removeFromSuperview];
}
- (void)moviePlayerPlaybackStateDidChange:(NSNotification*)notification
{
if (self. mpController.isPreparedToPlay) {
[self. mpController play];
}
}
And make sure movieURL is correct and video exist by this provided url
I would like to stop the audio with AvAudioPlayer but when another view dissapear, There are two views:
The problem is that when view2 disappear, the audio doesn't stop... How I should do?
View1.h
#property (nonatomic, retain) AVAudioPlayer *audioPlayer;
- (IBAction)playAudio:(id)sender;
- (IBAction)stopAudio:(id)sender;
View1.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self playSound];
}
- (void) playSound
{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"simpsonsTheme"
ofType:#"mp3"]];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
//[self.audioPlayer play];
[self playAudio:audioPlayer];
}
- (IBAction)playAudio:(id)sender {
[audioPlayer play];
}
- (IBAction)stopAudio:(id)sender {
[audioPlayer stop];
}
And View2.m
-(void)viewWillDisappear:(BOOL)animated{
view1 = (View1 *)[[UIApplication sharedApplication] delegate];
[view1 stopAudio:view1.audioPlayer];
}
In the View2 I import the View1 to do that.
Thanks
Your app delegate is not a view controller. Maybe you want [[UIApplication sharedApplication] delegate].window.rootViewController.
As you've seen, that's fragile. Instead of having pointers between your viewcontrollers, you could use have looser coupling and use a "stop" NSNotification. It may even be useful elsewhere in your application.
Define
NSString *StopPlayingVideoNotification = #"StopPlayingVideo";
So both views can see it, so put extern NSString *StopPlayingVideoNotification; in one of your header files.
In View1.m's init:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stopAudio:) name:StopPlayingVideoNotification object:nil];
Add a dealloc to View1:
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:StopPlayingVideoNotification object:nil];
}
In View2.m
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] postNotificationName:StopPlayingVideoNotification object:self];
}