I have a separate View Controller that holds some Audio Message (URL with mp3 files). Here's the code I use to start playing a message:
- (void)playAudioMsg
{
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategorySoloAmbient error: nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://blahblahblah.mp3"]];
NSData *data = [NSData dataWithContentsOfURL:URL];
audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
audioPlayer.numberOfLoops = 0;
audioPlayer.delegate=self;
[audioPlayer play];
}
The first time I open this view controller and click on a message to play, it plays just fine.
Then I dismiss a view controller.
Then I open it again and click on the same audio message. And what happens it's like two separate AVAudioPlayers got created - one of which starts playing audio right away and another is with a one-second delay (it sounds like the first message plays with echo.
Most interesting is when I dismiss a view controller then one message stops playing and another one keeps playing in the background even though when dismissing a view controller, I call [audioPlayer stop].
Can anyone help me with this, please?
I got the solution.
The problem comes from the fact that when I call -(void) playAudioMsg {...} I do it using this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playAudioMsg) name:#"playAudioMsg" object:nil];
... which is declared inside - (void) viewDidLoad {...}. But then I totally forgot to remove that observer when leaving the ViewController:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"playAudioMsg" object:nil];
}
Without removing the observer and then coming back to the same page, it sets duplicate for the same observer, so the method playAudioMsg gets called twice.
Related
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.
Hi I'm playing the audio file in one view controller when i going the another view controller its still playing the audio how to pause the audio when we going back to another view controller.
NSString *audioPath = [[NSBundle mainBundle] pathForResource:#"audio" ofType:#"mp3" ];
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
[self.audioPlayer play];
Please tell where i have to put the pause code for the audio when I'm going for another view controller.
Thanks.
in your viewController dealloc method add code to stop your audioPlayer
- (void)dealloc {
if ([self.audioPlayer isPlaying])
[self.audioPlayer stop];
[super dealloc]; // call if you are not using ARC
}
You can also put the stop audio code in ViewWillDisappear method if you are going deeper into heirarchy
I use AVAudioPlayer to play sound on my app. I can stop the sound by just calling a method with [audioPlayer stop]; in it. But when I call the method from another ViewController the sound is not stopping. I already searched but I can't get the right answer. What I want is to stop the sound from another ViewController. Can someone help me? I am new to iOS.
I used this to add my sound file:
//Declare the audio file location and settup the player
NSURL *audioFileLocationURL = [[NSBundle mainBundle] URLForResource:#"alarm" withExtension:#"wav"];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileLocationURL error:&error];
[audioPlayer setNumberOfLoops:-1];
if (error) {
NSLog(#"%#", [error localizedDescription]);
[[self volumeControl] setEnabled:NO];
[[self playPauseButton] setEnabled:NO];
[[self alertLabel] setText:#"Unable to load file"];
[[self alertLabel] setHidden:NO];
} else {
[[self alertLabel] setText:[NSString stringWithFormat:#"%# has loaded", #"alarm.wav"]];
[[self alertLabel] setHidden:NO];
//Make sure the system follows our playback status
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
//Load the audio into memory
[audioPlayer prepareToPlay];}
And used [audioPlayer play]; to start the sound and to stop I used [audioPlayer stop];. It is working fine when I am on the same ViewController but when I change ViewController [myViewController.audioPlayer stop]; is not working. I am using Storyboard with this.
You can add the stop method in the current class and call that methos in the other class on button click.Please find the code snippet on the following link
Trigger AVAudioPlayer to stop all sounds and play selected except when playing(selected) button is clicked
Adding one more link Why does the AVAudioPlayer stop method not work when switching views
Declare the instance of AVAudioPlayer at .h file as Global.
#property (nonatomic, retain) AVAudioPlayer *theAudio;
You can stop this from another controller
[objViewController.theAudio stop];
This works for me ..Hope it helps you too..
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.
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