3

I have an audio app that is having some problems with the way iOS 5 has changed audio behaviors. When my app's audio is playing (AVAudioSessionCategoryPlayback), and a Clock.app alarm or timer is fired from the OS, the UIAlertView notification pops up, but without the audio alert. My application sound ducks fine to get out of the way of the audio alert, but the alarm app's audio alert does not sound.

Naturally, tons of support requests poured in over the iOS 5 change. I have solved this temporarily by setting kAudioSessionProperty_OverrideCategoryMixWithOthers which lets the alarm audio come through, but there are a few very undesirable side-effects when doing this:

  • Other app's audio can play with/over mine.
  • The remote control events are not routed to my app, but to iPod.app.

None of the above drawbacks are acceptable for my app's requirements. I have been hacking away at this for some time now but haven't been able to crack it. How can I setup my audio such that:

  1. My app's audio still uses the AVAudioSessionCategoryPlayback category for background audio.
  2. The Clock.app alarms still have their audio alerts make sound
  3. The app still responds to remote control notifications
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
coneybeare
  • 33,113
  • 21
  • 131
  • 183

1 Answers1

3

After writing this question I went to file a bug report on this. I created a small sample project that I thought would replicate the issue, but I could not replicate it! This caused me to dig in deep once again and try to figure out what was up here…

I fired up an iOS alarm, then I placed a break point in audioPlayerBeginInterruption: and traced through my code line by line in the debugger. I noticed that before my code ran (while I was paused in the debugger), the iOS 5 alarm was sounding! Luckily it still sounded even as I was stepping through my app, so I was able to figure out which pieces of code specifically caused it to stop sounding.

Part of my interruptionHandler is to (obviously) stop the internal audio of my app to let the interruption come through. I never thought to inspect this method before, but turns out the problem existed in there. My stop method would call prepareToPlay immediately after stopping to make resuming faster the next time.

[self.player stop];
[self.player prepareToPlay]; // <- iOS 5 alarm sound stopped here.

The docs state the prepareToPlay method

preloads buffers and acquires the audio hardware needed for playback, which minimizes the lag between calling the play method and the start of sound output.

Sounds reasonable, and this worked for lesser iOS versions. My hypothesis is that  must have made a change to the Clock.app alarm system such that the new alarm sounds use the hardware, whereas before it used the software. This is what I think is causing the iOS 5 alarms to be silent in some apps.

Removing the prepareToPlay lines caused the alarm to sound without using kAudioSessionProperty_OverrideCategoryMixWithOthers, thus solving all my issues laid out in this question.


TL;DR

Remove the prepareToPlay calls from your stop sound code logic. It will take a microsecond longer to start later, but will allow interruptions to sound.

coneybeare
  • 33,113
  • 21
  • 131
  • 183