AVPlayer video not resuming after app become Active - ios

AVPlayer video not resuming from where it left, instead video starts from beginning. Here is my code.Can anyone help me??
-(void)appEnteredForeground:(NSNotification*)notification {
if(playerViewController.player.status == AVPlayerStatusReadyToPlay &&
playerViewController.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
total_duration = self.playerViewController.player.currentItem.duration;
[self.playerViewController.player seekToTime:currentTime];
[_playerViewController.player play];
}
}
-(void)appEnteredBackground:(NSNotification*)notification {
[playerViewController.player pause];
currentTime = [playerViewController.player currentTime];
[playerViewController.player seekToTime:currentTime];
}

1.It's seek to time problem, when u ask it to seek to time, it can't be done as it's already in background. Why did u seek to time when u enter background? pause should do just fine. remove the following line.
[playerViewController.player seekToTime:currentTime];
2.you had better pause in resign active notification instead of background notification. because the last one shall be triggered in a few seconds later after pressing the home button
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(becomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(resignActive) name:UIApplicationWillResignActiveNotification object:nil];
}
- (void)becomeActive {
NSLog(#"active");
if(playerViewController.player.status == AVPlayerStatusReadyToPlay &&
playerViewController.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
total_duration = self.playerViewController.player.currentItem.duration;
[self.playerViewController.player seekToTime:currentTime];
[_playerViewController.player play];
}
}
- (void)resignActive {
NSLog(#"resign active");
[playerViewController.player pause];
currentTime = [playerViewController.player currentTime];
}

Related

Crashed: AVAudioSession Notify Thread in iOS

I am getting EXC_BAD_ACCESS crash that occurs in the AudioToolBox. How to handle interrupts properly?
Please have a look at crashlytics screenshot for more info.
My audio streaming player was crashing when I get a phone call/ faceTime. It was actually an older class with Non ARC. Simply Add an InterruptionNotification Observer for the streaming class, and if the streaming class is playing we need to pause the player instance while interrupt begins.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleInterruptionChangeToState:) name:#"ASAudioSessionInterruptionOccuredNotification" object:nil];
- (void)handleInterruptionChangeToState:(NSNotification *)notification {
AudioQueuePropertyID inInterruptionState = (AudioQueuePropertyID) [notification.object unsignedIntValue];
if (inInterruptionState == kAudioSessionBeginInterruption){
if ([self isPlaying]) {
[self pause];
pausedByInterruption = YES; //a global Bool variable
}
}
else if (inInterruptionState == kAudioSessionEndInterruption){
AudioSessionSetActive( true );
if ([self isPaused] && pausedByInterruption) {
[self pause]; // this is actually resume
pausedByInterruption = NO;
}
}
}
Hope it helps.

AVPlayerItemDidPlayToEndTimeNotification not called

I have a video on a screen that must be played with an infinity loop.
So I wrote :
self.player = [AVPlayer playerWithPlayerItem:avItem];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_player currentItem]];
[_player play];
And I fallback method is :
- (void)playerItemDidReachEnd:(NSNotification *)notification {
[_player.currentItem seekToTime:kCMTimeZero];
[_player play];
}
It works well but sometimes it seems that my fallback is not called. The video is freezing at the end and never played again. It's happening randomly ...
Do you have an idea ?
You can just set a boundary time observer.
- (id) setupBoundaryEndWith:(NSArray*)array
{
__weak MY_AVPlayer* weakself = self;
return [self addBoundaryTimeObserverForTimes:array queue:NULL usingBlock:^{
[weakself stopAVPlayerAndLoopOrTriggerNextTrack];
}];
}
[_player currentItem] is null, since you haven't started playing yet. I would suggest either to explicitly add the AVPlayerItem (ideally) or register to notifications after starting the playback (reverse the 2 last lines).
I have not tried the 2-nd solution, so it might not work, if it takes some time to start the playback. If that is the case, I suggest setting an NSTimer to trigger a second later and then register.

Problems with applicationWillEnterForeground

My code for application will Enter Foreground is given below. I am working on the iOS simulator. What I am trying in my code is, when a player clicks home button while game is going on and returns back to the game after sometime, I want the game to be in pause state. Although my code pauses the game, but it does not pause it immediately. That is, when I go to my game again, there is 1 second of movement before everything pauses.
-(void)applicationWillEnterForeground:(UIApplication *)application
{ [[NSNotificationCenter defaultCenter] postNotificationName:#"didEnterForeground" object:self];
}
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(handleEnterFg)
name: #"didEnterForeground"
object: nil];
-(void) handleEnterFg
{
if (gameIsOver== NO)
{
[myTimer pause];
gamePause = YES;
self.scene.view.paused = YES;
}
}
-(void) handleEnterBg
{
if (gameIsOver== NO)
{
[bgPlayer pause];
[self childNodeWithName:#"pauseButton"].zPosition = -10;
[self childNodeWithName:#"playButton"].zPosition = 160;
}
}
Thank you!
You need to pause the game when you receive applicationWillEnterBackground if you want to pause it immediately.

How to display ToolBar Buttons on MPMoviePlayerController

I am trying to display UIToolBar with BarButtonItems on MPMoviePlayerController. Not sure how will I implement it.
I am trying to play the video file when user taps on one of the cell of UITableView. At that time I would like to give an option to user to share the video on FB or tweeter.
Not sure how will I display the share BarButtonItem on MPMoviePlayerController. I am trying to implement something similar to the photo app that comes with iPhone.
Can anyone please help me out?
Thank you!
MPMovieplayer is not the right choice for this purpose. You can create a custom movie player with AVPlayer(found under AVFoundation.framework) that would serve your purpose. Create any normal ViewController in your project and add an AVPlayer with code something like below:
-(void)viewDidLoad {
//prepare player
self.videoPlayer = [AVPlayer playerWithURL:<# NSURL for the video file #>];
self.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndPause;
//prepare player layer
self.videoPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];
self.videoPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.videoPlayerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:self.videoPlayerLayer];
//add player item status notofication handler
[self addObserver:self forKeyPath:#"videoPlayer.currentItem.status" options:NSKeyValueObservingOptionNew context:NULL];
//notification handler when player item completes playback
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.videoPlayer.currentItem];
}
//called when playback completes
-(void)playerItemDidReachEnd:(NSNotification *)notification {
[self.videoPlayer seekToTime:kCMTimeZero]; //rewind at the end of play
//other tasks
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"videoPlayer.currentItem.status"]) {
//NSLog(#"player status changed");
if (self.videoPlayer.currentItem.status == AVPlayerItemStatusReadyToPlay) {
//player is ready to play and you can enable your playback buttons here
}
}
}
As this would be normal view controller, you can add a toolbar buttons/buttons to it, for playing/sharing, etc. and trigger the player actions and any other related action like below:
-(IBAction)play:(id)sender {
[self.videoPlayer play];
}
-(IBAction)pause:(id)sender {
[self.videoPlayer pause];
}
//etc.
Also make sure to remove the observers in your dealloc:
-(void)dealloc {
//remove observers
#try {
[self removeObserver:self forKeyPath:#"videoPlayer.currentItem.status" context:NULL];
}
#catch (NSException *exception) {}
#try {
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.videoPlayer.currentItem];
}
#catch (NSException *exception) {}
//other deallocations
[super dealloc];
}
More detailed and sophisticated explanation of the process can be found under apples companion guide, available here

MPMoviePlayerViewController stops after a few seconds

I have an app in which I am streaming a live TV channel in one of tabs. I am using MPMoviePlayerViewController. I did declare my MPMoviePlayerViewController in my header file and synthesize it in my implementation file.
Here's my viewDidAppear:
- (void)viewDidAppear:(BOOL)animated
{
NSURL *movieURL = [[NSURL alloc]initWithString:#"http://mysuperURL"];
moviePlayerController = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self checkIt];
}
And my checkIt function
- (void) checkIt {
if ([[moviePlayerController moviePlayer] loadState] == MPMovieLoadStateUnknown) { // before you wreck yourself
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(checkIt) userInfo:nil repeats:NO];
} else {
[moviePlayerController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:moviePlayerController animated:YES];
}
}
However the video freezes after two seconds and the app stops responding.
You should use the MPMoviePlayerNotifications instead of manually polling the current state.
For example - somewhere in you initializing code:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerLoadStateDidChange:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
Now implement a notification handler:
- (void)MPMoviePlayerLoadStateDidChange:(NSNotification *)notification
{
NSLog(#"loadstate change: %Xh", movieController_.loadState);
}
And somewhere within your deinitializing code:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
Also note that MPMoviePlayerController.loadState is a bitmap -> you need to mask out the value you want to check for.
For Example:
if ((movieController_.loadState & MPMovieLoadStatePlayable) == MPMovieLoadStatePlayable)
{
NSLog(#"yay, it became playable");
}
Asfar as my knowledge concern usage of timer it is freezing and it takes time streaming also.

Resources