views:

120

answers:

2

In the Audio Session Cookbook there is a section on "Checking if Other Audio is Playing During App Launch".

I'm using MonoTouch (but feel free to give an Objective-C answer, the API is the same), so the code from that document looks something like this:

bool otherAudioPlaying = AudioSession.OtherAudioIsPlaying;
if(otherAudioPlaying)
    AudioSession.Category = AudioSessionCategory.AmbientSound;
else
    AudioSession.Category = AudioSessionCategory.SoloAmbientSound;

The upshot is that, if my app is started with iPod music playing, that iPod music will keep playing and prevent me from using the hardware audio decoder (which I don't need anyway). If there's no iPod music playing when my app starts, I can use the hardware decoder.

I can then use the value of otherAudioPlaying to determine whether or not to start playing my own music.

Now that works just fine on the older operating systems that don't support multitasking. But with multitasking the user can leave my app (backgrounding it), start music playing on the iPod, and re-enter my app. Then their iPod music will be silenced and my music will start playing again.

What I would like to have happen is have the iPod music continue playing when my application returns to the foreground - even if my own music was playing (and using the hardware decoder) when my application was backgrounded.

(And, in reverse - if my application was backgrounded with no music playing, I'd like to detect if I can start playing music when it returns).

How can I do this? (And preferably without abruptly cutting off my audio, maintaining the nice fade-out that usually happens.)

EDIT: I should also point out that I'm doing all my audio work off the main thread.

A: 

Why not just take care of implementing it in your app delegate multitasking messages? On background, suspend your audio (storing current playback position if necessary), and spin it back up when the application resumes focus.

Just to clarify a bit more: respond to applicationDidEnterBackground: in your delegate by resetting your audio player state, and respond to applicationWillEnterForeground: by setting it back up the way you do now. You could also have the object that sets up audio play respond to UIApplicationWillEnterBackgroundNotification/UIApplicationWillEnterForegroundNotification through NSNotificationCenter, that would probably be a bit easier at the expense of abstracting away what your app does exactly on background out of your app delegate class.

refulgentis
I know about `applicationDidEnterBackground`, and I assume a solution will involve responding to it. What I'm trying to figure out is what the "suspend your audio" and "resetting your audio player state" bits entail.
Andrew Russell
Hmm...I guess I don't understand. If this a question about AudioSession, you know how to start it, I assume similar methods stop it? If you really don't know I'll look up the docs and answer again. On a more banal level: I can't tell you how to reset your audio player state because I don't know how you set it up. iOS would consider it reset if you stop it.
refulgentis
My audio player is just a simple hardware AudioQueue, essentially what is described in the "Audio Queue Services Programming Guide" (except that it is handled on a different thread to the main one where I receive notifications). The thing is that interacting with the AudioQueue/AudioSession APIs during applicationDidEnterBackground results in odd behaviour or crashing. Unfortunately the documentation (as far as I could tell) doesn't describe the way these two parts of the API interact.
Andrew Russell
A: 

Regarding your last comment on refulgentis's answer, you could pause your music in applicationWillResignActive and leave state saving operations and cleanup for applicationDidEnterBackground. This might be better for avoiding any odd behaviour during the background transition state.

Nick Toumpelis