AVPlayer stops playing when screen is unlocked (but works when locked) - ios

I am trying to have my AVPlayer play audio in the background, even when the screen is locked. Right now, it does play when the screen is locked, but as soon as it is unlocked, it stops.
In the application delegate I have
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
and I play the sound by doing
AVPlayer *player = [[AVPlayer alloc]initWithURL:self.mp3URL];
_audioPlayer = player;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_audioPlayer currentItem]];
[_audioPlayer play];
I also have the required background modes set to "App plays audio" in the info.plist. Any ideas?

There's nothing i see as a reason in the code you posted. perhaps you are reactivating the audio session causing it to stop when the view shows? The error is not in the code you posted.

Related

iOS AVPlayer showing screen with a cross line on Play icon

Screen Shot of AVPlayer error
Below is the code snippet, url is the the video url. This error occurs randomly.
I'm unable to trace what is the issue. Also the video is stored in cloud and video buggers to play on the AVPlayer. Is anything missing in the below code.
+ (void)presentVideoForURL:(NSURL *)URL parentViewController:(UIViewController *)parentViewController {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *setCategoryError;
if (![audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError]) {
Error(#"setCategoryError %#", setCategoryError.localizedDescription);
}
NSError *activationError;
if (![audioSession setActive:YES error:&activationError]) {
Error(#"activationError: %#", activationError.localizedDescription);
}
AVPlayer *player = [[AVPlayer alloc] initWithURL:URL];
AVPlayerViewController *playerController = [[AVPlayerViewController alloc] init];
playerController.player = player;
[parentViewController presentViewController:playerController animated:YES completion:^{
[player play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playbackDidFinish:) name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playbackDidFinish:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:player.currentItem];
}];
}
Check the following 2 scenarios.
1) Check whether the url is correct or not.
2) If your network is slow and AVPlayer is not getting adequate data into it's buffer,it stops loading and shows a UI like you mentioned (A cross bar in play button).So try using high sped network.
If this is the issue,you can restart the player using the playback stall notification.
I had the 2nd issue and I fixed the same like this.

Play MPMoviePlayerController audio stream in background

So I have this app where I play videos and when you exit the app I would like the user to continue to listen to the audio of the video. I use MPMoviePlayerController to play the video and it works in the app perfectly fine. I also setup AVAudioSession up before I play the video and I get no error.
NSError *audioSessionError;
NSError *activationError;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&audioSessionError];
[audioSession setActive:YES error:&activationError];
I also set in plist background modes audio. But the video with the audio both stop playing when you close the app. I've also imported the AVFoundation framework.
Simply set Application does not run in background to NO in .plsit file
You need to make couple of changes in plist file.i.e.
1) Set Required background mode to App plays audio
2) set Application does not run in background to YES.
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Then, you need to write these much code in AppDelegate
Now, you can easily run audio while phone screen locks or goes in background.
This code worked for me, first you must to give your app permissions to keep playing music in the background (In your .plis), after that go to the wished class and implement this code, first the imports and the the method to play the music.
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPMediaItem.h>
#import <AVFoundation/AVFoundation.h>
---- o ----
-(void) playMusic{
[[AVAudioSession sharedInstance] setDelegate: self];
NSError *myErr;
// Initialize the AVAudioSession here.
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&myErr]) {
// Handle the error here.
NSLog(#"Audio Session error %#, %#", myErr, [myErr userInfo]);
}else{
// Since there were no errors initializing the session, we'll allow begin receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
//initialize our audio player
audioPlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:#"http://www.cocoanetics.com/files/Cocoanetics_031.mp3"]];
[audioPlayer setShouldAutoplay:NO];
[audioPlayer setControlStyle: MPMovieControlStyleEmbedded];
audioPlayer.view.hidden = YES;
[audioPlayer prepareToPlay];
[audioPlayer play];
}//end playmusic
You need to turn on Background Modes in capabilities.

How to pause background Music in ios

I am playing video in my application
_player = [[MPMoviePlayerController alloc] init];
_player.view.frame = CGRectMake(0, 60, frame.size.width,frame.size.height - 130);
_player.movieSourceType = MPMovieSourceTypeStreaming;
_player.fullscreen = NO;
[_player setScalingMode:MPMovieScalingModeAspectFill];
_player.controlStyle = MPMovieControlStyleNone;
[_player setContentURL:[NSURL URLWithString:mediaUrl]];
[_player play];
And i have to do some configuration -
1- If device is silent then play video with full volume.
2- If device is playing any music in another application then have to pause the background songs and play again when video play completed.
So i searched a lot then found following solutions -
For 1-
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
its working perfectly when device is silent.then its playing in full volume.
For 2- Both background song and Video audio playing both, I am doing following -
- (void)viewWillAppear:(BOOL)animated {
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
}
-(void)viewWillDisappear:(BOOL)animated {
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setActive:NO error:nil];
}
But its not working, its stoping background music but not playing again.
Maybe because viewWillDisappear is not called when the app goes to background.
Furthermore:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:NO error: nil];
does not work to avoid background music once it has been activated.

Can't play sound when app is in background mode

In Info.plist I added:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>location</string>
</array>
...
I load the sound like this:
NSURL *urlFail = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/criticalSound.wav", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFail error:&error];
[audioPlayer setDelegate:self];
audioPlayer.numberOfLoops = 0;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[audioPlayer setVolume:1.0];
if (audioPlayer == nil){
}else{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
if (musicPlayer.playbackState == MPMusicPlaybackStatePlaying)
{
self.wasMusicAppOn = YES;
[musicPlayer pause];
}else{
self.wasMusicAppOn = NO;
}
[audioPlayer play];
}
This works fine when app is active.
But I have a location update when application is in background and from time to time (like when user pass 500m) I should play this sound.
So I put this code there.
Anyway problem is that sound plays when app is in foreground but doesn't work when it is in background.
What am I doing wrong here?
As far as I've been able to tell, you must actually be playing sound while going into the background to be able to continue playing sound in the background.
Also, the description for AVAudioSessionCategoryAmbient states that "Your audio is silenced by screen locking and by the Silent switch (called the Ring/Silent switch on iPhone)".
You need to make couple of changes in plist file.
1) Set Required background mode to App plays audio
2) set Application does not run in background to YES.
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Then, you need to write these much code in AppDelegate
Now, you can easily run audio while phone screen locks or in background.
It works fine for me. :)
for more please refer to Playing Audio in background mode and Audio Session Programming Guide

MPMoviePlayerController playing audio stream in the background

I am running into trouble with playing an audio stream when the application enters background.
I use the code to start the stream:
NSURL *mediaURL = [NSURL URLWithString:#"http://url.to.my.stream"];
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc] initWithContentURL:mediaURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
[mp setControlStyle:MPMovieControlStyleFullscreen];
[mp setMovieSourceType:MPMovieSourceTypeStreaming];
[mp setFullscreen:YES];
[self.view addSubview:[mp view]];
[mp prepareToPlay];
[mp play];
It works perfect. But allthough I set the flag 'App plays audio' in the property list when the app enters background the stream stops playing.
How do I make my application play the audio stream in the background?
Best regards and thanks a lot for help!
I didn't tried it myself but this looks promising: iOS Multitasking: Background Audio
Once the project has been created go to APP-Info.plist and add
UIBackgroundModes as a new row. It should then create the array.
Open the array and to the right of Item 0 set it to audio.
EDIT
Is your AVAudioSession set up properly?
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
This code worked for me, first you must to give your app permissions to keep playing music in the background (In your .plis), after that go to the wished class and implement this code, first the imports and the the method to play the music.
#import <MediaPlayer/MPNowPlayingInfoCenter.h>
#import <MediaPlayer/MPMediaItem.h>
#import <AVFoundation/AVFoundation.h>
---- o ----
-(void) playMusic{
[[AVAudioSession sharedInstance] setDelegate: self];
NSError *myErr;
// Initialize the AVAudioSession here.
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&myErr]) {
// Handle the error here.
NSLog(#"Audio Session error %#, %#", myErr, [myErr userInfo]);
}else{
// Since there were no errors initializing the session, we'll allow begin receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
//initialize our audio player
audioPlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:#"http://www.cocoanetics.com/files/Cocoanetics_031.mp3"]];
[audioPlayer setShouldAutoplay:NO];
[audioPlayer setControlStyle: MPMovieControlStyleEmbedded];
audioPlayer.view.hidden = YES;
[audioPlayer prepareToPlay];
[audioPlayer play];
}//end playmusic

Resources