Background Audio in iOS - ios

I'm trying to build an iOS App (iOS > 5.0). It should play music files when a timer, set by the user, ends. Here is my setup what if done so far:
I use avplayer
I've set Background Modes in my plist to "App plays Audio"
in my appDelegate I have:
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
before a song is going to be played a set:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
[[AVAudioSession sharedInstance] setActive:YES error:&sessionError];
i notify my application on "playerItemDidPlayToEnd", stop the player and tell other apps like the music.app to become active again
_avPlayer = nil;
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setActive:NO withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:&sessionError];
This works fine. You can have your music app playing in background. My App starts to play a song the music app fades away. My song is played and if its finished the music app continues to play. But only as long as my app isn't in background.
In background I get the error:
Error Domain=NSOSStatusErrorDomain Code=560161140 "The operation couldn\u2019t be completed. (OSStatus error 560161140.)"
Is it possible that both combinations of, playing in background (on custom events) and switching between f.e. music.app and my app in background isn't possible?
Here a the code of my player model: http://pastie.org/4830995

I think your problem might be with background handling. You need to override this function on app delegate.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
__block UIBackgroundTaskIdentifier task = 0;
task=[application beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Expiration handler called %f",[application backgroundTimeRemaining]);
[application endBackgroundTask:task];
task=UIBackgroundTaskInvalid;
}];
}
your application will get killed after 6 minutes unless sound is played. If your user set timer for more then 6 minutes, what you could do is to play short quite sound every 5.5 minutes to keep you app alive and start new background task. Also you have to consider that lot of thing will not get executed in background. I did some stuff somewhat similar to what you are doing. What I did was created custom subclass of NSObject witch handled music playback and application expiration stuff. And made it a strong property on my delegate as lot of functions and notifications will not run on you VC in the background.
Although if you just want to play a sound this might not be the best approach. Maybe just sending local notification would do.
Hope this helped.

Did you register your app to keep running in the background as an audio app? To do so, add the UIBackgroundModes key to your Info.plist file and set its value to audio.

Related

iOS AVAudioSession ducking is slow and synchronous

In iOS, I'm trying to duck the Music app's music when playing some sound effects. In case you don't know, "ducking" simply means that the music volume gets a bit down before playing my sound, then the sound plays, and then the music volume gets back its initial volume.
For ducking, I'm setting AVAudioSession category to AVAudioSessionCategoryAmbient with option AVAudioSessionCategoryOptionDuckOthers, and then activating/deactivating the session (and playing the sound in-between, obviously). It works well, but the volume changes seem to be done in the same thread as the call, and the app hangs while the volume is being modified.
If you want to replicate the behavior, I think the fastest route is to start a new SpriteKit project, which will give you the sample, ship rotating project. Then put the following code in the touchesBegan:withEvent method:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient withOptions: AVAudioSessionCategoryOptionDuckOthers error: nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[AVAudioSession sharedInstance] setActive:NO error:nil];
Next run the app in an iOS device, put some music in the Music app and touch the screen to create ships and duck the music. You'll hear the ducking, but also see the ships freezing on the screen.
Is this normal? What would be the simplest way to avoid the app freezing while the ducking is made?
By the way, I'm using an iPhone 5S on iOS 8.1. Also, I'm using this in a Unity3D plugin. How can I duck the Music app from Unity itself?
You can try putting the AVAudioSession calls on a different thread. Then they won't be blocking the main (UI) thread. This is especially for setActive, which takes a noticeable amount of time to complete.
dispatch_queue_t myQueue = dispatch_queue_create("com.myname.myapp", nil);
dispatch_async(myQueue, ^{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient withOptions: AVAudioSessionCategoryOptionDuckOthers error: nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
});
This question also seems relevant: iOS AudioSessionSetActive() blocking main thread?

MPMusicPlayerController Play music while app is in background

Hope this question doesn't get down voted - I haven't seen anything in the documentation.
I want to play music from the ipod library while the app is in the back ground.
I am creating the music player using the default mechanism.
-(void)viewWillAppear:(BOOL)animated
{
MPMusicPlayerController *myPlayer =
[MPMusicPlayerController applicationMusicPlayer];
// assign a playback queue containing all media items on the device
[myPlayer setQueueWithQuery: [MPMediaQuery songsQuery]];
// start playing from the beginning of the queue
[myPlayer play];
}
As soon as the app enters the background the music stops playing. I would like it to continue playing though.
I do not want to use the iPodMusicPlayer option
How can I do this?
You should set background audio mode in the project settings (Project settings > Capabilities > Background modes > Audio and AirPlay) like it's shown on the screenshot below:
Also you should set Audio Session Category in the appDelegate (in the didFinishLaunching method). Example is shown below:
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
I have same issue. I searched even after added flag in plist. It will not work because :
The applicationMusicPlayer does not support background music. Use
MPMusicPlayerController's systemMusicPlayer instead. It shares the
state with the built-in System player and music will continue to play
when your app enters the background.
Other Solution is :
You can use AVAudioPlayer to play either streamed or local(bundle) audio. It even allows you to play multiple audio file at the same time having an AVAudioPlayer instance for each.
Note : iPodMusicPlayer is deprecated. so Instead of this use systemMusicPlayer.

iOS: Keep playing music in background with Spotify SDK

I'm using the Spotify iOS SDK and have a question about the background music.
When a user locks the phone or presses the Home button I want my app to continue to play the music. How is this possible?
I've tested
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Together with adding "Required background modes" to the apps plist.
Does this require that the AVAudioPlayer is used? Since I'm using the Spotify streamingPlayer its not possible.
Background playback should work just fine. You do need the audio item in your UIBackgroundModes Info.plist entry, though. Also, make sure you test on a device - I know remote control events don't work in the iOS Simulator, and that might be the case for background audio as well.
The iOS SDK will automatically set up the AVAudioSession for you, so you don't need to do that.
You might find this answer helpful, which is more in-depth: Background Audio with cocoalibspotify.

Stop UILocalNotification Sound on slide to view

In my alarm app, I am scheduling an alarm on some time.
With the app in foreground I lock my iPhone (iOS7, I haven't tried with iOS6).
Now when the notification sound starts, I view the local notification by using the "Slide to view" on my lock screen, and when the app opens, I also play the sound using AVAudioPlayer.
So the problem is notification sound continuously ringing until 30.0 seconds.
Is this iOS issue or in the code I need to integrate any method etc.?
Thanks
according to another SO post, this is a bug with iOS 7 where the sound doesn't stop when the user 'slides to view' if passcode lock is turned off.
possible fixes can include turning on passcode lock or using this code (taken from the linked post).
- (void)applicationWillEnterForeground:(UIApplication *)application
{
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
[session setActive:YES error:nil];
MPMusicPlayerController *musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
[musicPlayer setVolume:0.0f];
}
This bug has been fixed as of iOS 8

is it possible to play avaudioplayer in background mode?

I am doing an Alarm application,in my app after lunching app in device i am saving one alarm and i close the app.When alarm is coming, its not ringing But at that time update method is calling i am getting notification. after that i set another alarm and i keep the app open at that time i got both alarm sound and one alertview after that all the alarms are also coming in background mode with sound.
I did change in info.plist in Required background modes and in coding also i am doing like this
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
Please suggest me what should i do?
For alarm purpouses it's better to use Local notifications or Calendar, I think.

Resources