The app must to play a sound when it is in background. In the capabilities background fetch and audio & airplay are checked.
The method called for play the sound is that
-(void)playSound
{
NSString* str = [[NSBundle mainBundle] pathForResource:#"alarm4" ofType:#"wav"];
NSURL* url = [NSURL fileURLWithPath:str];
NSError* erreur;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&erreur];
if(!erreur)
{
[self.audioPlayer setVolume:1];
[self.audioPlayer setNumberOfLoops:-1];
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
}
else
NSLog(#"erreur de chargemnt %#", [erreur localizedDescription]);
}
Can you give me some advice, please?
My advice is: Don't even dream of such a thing. In general, you can't do it.
You can continue playing a sound as you go into the background, but you cannot spontaneously produce a sound out of the blue in an already backgrounded app. It would be terrible if this could happen, because the user would not know where the sound is coming from, the sound could mess up the user's music listening experience, etc.
You should ask yourself why you think you need to do such a thing in the first place. You probably don't need to.
(Some Apple apps can do it. For example, the Clock app produces a repeating alarm sound out of the blue, in the background. But you, as you have probably noticed by now, are not Apple.)
Related
I have an app that uses AVAudioPlayer to play sound effects, music, etc. It works fine for just about every user (100,000+ users), but I've had several reports of sound not playing at all even though sound effects are working on other apps on the same device. The bug has gone away for some users after an app restart/device reboot, but for others it continues to persist. AVSpeechSynthesizer isn't working for these users either.
I haven't been able to reproduce the bug to see if the AVAudioPlayer is throwing an error, so I'm not sure if it is - but I don't see why it would be working fine for 99.9% of users and not this tiny subset.
Has anyone else run into something like this?
Here's the code I'm using to set up the player:
[[AVAudioSession sharedInstance] setCategory:#"AVAudioSessionCategoryAmbient" error:nil];
NSString *file = [filename stringByDeletingPathExtension];
NSString *extension = [filename pathExtension];
NSURL *soundFileURL = [[NSBundle mainBundle] URLForResource:file withExtension:extension];
self.soundPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
[self.soundPlayer1 prepareToPlay];
I have a working AudioServicesPlaySystemSound code to run a 10s background music.
Is there a way for me to loop this audio every 10s ? I want it to run forever until an action is triggered to stop the audio (e.g: a button is pressed to stop the loop)
I read an article about dispatch_after and thought that it might be an appropriate way to create the loop.
Switch to AVAudioPlayer instead. Not only can you specify a number of times to play the sound, but you have more control over the sound, including volume level.
It isn't that much harder. For example, here is how you would play a sound, looped indefinitely:
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer *player = [{AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
player.numberofLoops = -1;
[player play];
and this is how you would stop it:
[player stop];
I have tried everything I can find to try and get my app to play an mp3. I have a few 2-3 second mp3s that play as sound effects that work, but I am trying to play a 15s mp3 without any luck.
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource: #"test" withExtension: #"mp3"] error:&error];
if (error) {
NSLog(#"Error creating audio player: %#", [error userInfo]);
} else {
if([audioPlayer play] == FALSE) {
NSLog(#"Fail %#", error);
}
}
NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval: 15.0 target: self
selector: #selector(stopMusic) userInfo: nil repeats: NO];
I doubt the timer has anything to do with it but thought I would include it just in case. Basically my error checks are not getting triggered at all. It "should" be playing properly but no sound is coming out, and no errors are being displayed.
I have tried a few other things to try and get this working, and I have tried without the timer. I can't find a decent guide. I don't need a full blown media player, just some background music for an UIScreenViewController.
I have also tried the following code, which works good with short MP3s, not with the longer MP3 I want to play.
NSString *path = [[NSBundle mainBundle] pathForResource:#"bgmusic" ofType:#"mp3"];
NSURL *pathURL = [NSURL fileURLWithPath : path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
Please help, I have spent hours trying to sort this. It seems apple re-jig their audio every time they release an OS.
I did a little testing for you: It turned out that music files aren't added to target by default in Xcode 5. Therefore URLForResource:error: likely returns nil.
Try removing the mp3 from your project. Then add it again and this time make shure you add it to your target:
The other thing is: It seems like you're defining the AVAudioPlayer inside a method. You normally set up a #property for your audio player because otherwise its life is limited to the method - and the music stops playing after you reach the end of the method.
I’ve read many articles/posts on this topic, but I’m still unable to play a sound while the screen is locked.
In viewDidLoad, I initialize the audio session and set the audio property to kAudioSessionCategory_MediaPlayback:
AudioSessionInitialize(NULL, NULL, interruptionListenerCallback, self);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
AudioSessionSetActive(true);
I then initialize my AVAudioPlayer variable (audioPlayer):
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: #"click" ofType: #"wav"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: &error];
[fileURL release];
I added “App plays audio” to a “Required background modes” section of my info.plist.
I added AVAudioPlayerDelegate and AVAudioSessionDelegate to my view controller’s *.h file (although I don’t know if that was necessary).
I play the (very short) sound periodically (~1x per second):
[audioPlayer play]
The sound plays fine when the screen is unlocked, but stops playing when I lock it. When I then unlock the screen, the (queued) sounds are played.
Ideas? Thanks!
Thanks holex:
I got "App plays audio" from http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_background-audio/.
If you add a row with UIBackgroundModes to the plist, it's automatically populated and includes this and six other background modes. If you Google "App plays audio" and UIBackgroundModes you'll see plenty of hits.
[I would have replied via a Comment rather than an Answer, but alas, I don't have the reputation.]
It seems the problem is that I'm starting to play the sound after the screen has been locked. That's mostly answered in How to play sounds in locked mode on iPhone.
I have an app which plays and controls music across different ViewControllers. To do this, I created two instances of AVAudioPLayer in the app delegate's DidFinishLaunchingMethod:
NSString *path = [[NSBundle mainBundle] pathForResource:#"minnie1" ofType:#"mp3"];
NSURL *path1 = [[NSURL alloc] initFileURLWithPath:path];
menuLoop =[[AVAudioPlayer alloc] initWithContentsOfURL:path1 error:NULL];
[menuLoop setDelegate:self];
menuLoop.numberOfLoops = -1;
[menuLoop play];
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"minnie2" ofType:#"mp3"];
NSURL *path3 = [[NSURL alloc] initFileURLWithPath:path2];
gameLoop=[[AVAudioPlayer alloc] initWithContentsOfURL:path3 error:NULL];
gameLoop.numberOfLoops = -1;
[gameLoop setDelegate:self];
[gameLoop prepareToPlay];
After this I call it in various viewControllers, to stop or restart using code like:
- (IBAction)playGameLoop{
NSLog(#"Begin playGameLoop");
FPAppDelegate *app = (FPAppDelegate *)[[UIApplication sharedApplication] delegate];
if ([FPAVManager audioEnabled] == NO){
//DO NOTHING
}
else {
if (app.gameLoop.playing ==YES ) {
//DO NOTHING
}
else { [app.gameLoop play];
NSLog(#"End playGameLoop");
}
}
The audio files play fine the first time and they stop when asked to stop. Though, on iOS4 devices, they won't start replaying when called again.
Thanks!
From the docs:
Calling this method [stop] or allowing a sound to finish playing,
undoes the setup performed upon calling the play or prepareToPlay
methods.
The stop method does not reset the value of the currentTime property
to 0. In other words, if you call stop during playback and then call
play, playback resumes at the point where it left off.
Where you are looping the sounds, I would expect to be able to call stop and then call play. But I have fuzzy recollection of running into this myself. I found that calling pause, rather than stop, was a better solution. Especially since I could then call play again to resume play. Calling stop always seemed to require calling prepareToPlay again before calling play, at least in my experience.
It's possible that there were some changes in the API implemetation between iOS4.x and iOS5, too. You should check the API diffs on the Developer web site to be sure.