Responding to Interruptions

Adding audio session code to handle interruptions ensures that your app’s audio continues behaving gracefully when a phone call arrives, a Clock or Calendar alarm sounds, or another app activates its audio session.

An audio interruption is the deactivation of your app’s audio session—which immediately stops or pauses your audio, depending on which technology you are using. Interruptions happen when a competing audio session from an app activates and that session is not categorized by the system to mix with yours. After your session goes inactive, the system sends a “you were interrupted” message which you can respond to by saving state, updating the user interface, and so on.

Your app may get suspended following an interruption. This happens when a user decides to accept a phone call. If a user instead elects to ignore a call, or dismisses an alarm, the system issues an interruption-ended message, and your app continues running. For your audio to resume, your audio session must be reactivated.

Audio Interruption Handling Techniques

Handle audio interruptions by registering for the appropriate NSNotification. What you do within your interruption code depends on the audio technology you are using and on what you are using it for—playback, recording, audio format conversion, reading streamed audio packets, and so on. Generally speaking, you need to ensure the minimum possible disruption, and the most graceful possible recovery, from the perspective of the user.

Table 3-1 summarizes appropriate audio session behavior during an interruption. If you use the AVAudioPlayer or AVAudioRecorder objects, some of these steps are handled automatically by the system.

Table 3-1  What should happen during an audio session interruption

After interruption starts

  • Save state and context

  • Update user interface

After interruption ends

  • Restore state and context

  • Reactivate audio session if app appropriate

  • Update user interface

Table 3-2 summarizes how to handle audio interruptions according to technology. The rest of this chapter provides details.

Table 3-2  Audio interruption handling techniques according to audio technology

Audio technology

How interruptions work

AV Foundation framework

The AVAudioPlayer and AVAudioRecorder classes provide delegate methods for interruption start and end. Implement these methods to update your user interface and optionally, after interruption ends, to resume paused playback. The system automatically pauses playback or recording upon interruption and reactivates your audio session when you resume playback or recording.

If you want to save and restore the playback position between app launches, save the playback position on interruption as well as on app quit.

Audio Queue Services, I/O audio unit

These technologies put your app in control of handling interruptions. You are responsible for saving playback or recording position and for reactivating your audio session after interruption ends.

OpenAL

When using OpenAL for playback, register for the appropriate NSNotification notifications—as when using Audio Queue Services. However, the delegate must additionally manage the OpenAL context. See “OpenAL and Audio Interruptions.”

System Sound Services

Sounds played using System Sound Services go silent when an interruption starts. They can automatically be used again if the interruption ends. Apps cannot influence the interruption behavior for sounds that use this playback technology.

Handling Interruptions From Siri

When your app is interrupted during playback by Siri, you must keep track of any remote control commands issued by Siri while the audio session is interrupted. During the interrupted state, keep track of any commands issued by Siri and respond accordingly when the interruption ends. For example, during the interruption, the user asks Siri to pause your app’s audio playback. When your app is notified that the interruption has ended, it should not automatically resume playing. Instead, your app’s UI should indicate that it is in a paused state.

The Interruption Life Cycle

Figure 3-1 illustrates the sequence of events before, during, and after an audio session interruption for a playback app.

Figure 3-1  An audio session gets interrupted
A timeline representation of an application's audio session getting interrupted by a phone call.

An interruption event—in this example, the arrival of a phone call—proceeds as follows. The numbered steps correspond to the numbers in the figure.

  1. Your app is active, playing back audio.

  2. A phone call arrives. The system activates the phone app’s audio session.

  3. The system deactivates your audio session. At this point, playback in your app has stopped.

  4. The system invokes your interruption listener callback function indicating that your session has been deactivated.

  5. Your callback takes appropriate action. For example, it could update the user interface and save the information needed to resume playback at the point where it stopped.

  6. If the user dismisses the interruption—electing to ignore an incoming phone call in this case—the system invokes your callback method, indicating that the interruption has ended.

  7. Your callback takes action appropriate to the end of an interruption. For example, it updates the user interface, reactivates your audio session, and resumes playback.

  8. (Not shown in the figure.) If, instead of dismissing the interruption at step (6), the user accepted a phone call, your app is suspended. When the phone call ends, the end interruption is delivered.

There is no guarantee that a begin interruption will have an end interruption. Your app needs to be aware of switching to a foreground running state or the user pressing a play button. In either case, determine whether your app should reactivate its audio session.

OpenAL and Audio Interruptions

When using OpenAL for audio playback, implement an interruption listener callback function, as you do when using Audio Queue Services. However, your interruption code must additionally manage the OpenAL context. Upon interruption, set the OpenAL context to NULL. After the interruption ends, set the context to its prior state.

Using the AVAudioPlayer Class to Handle Audio Interruptions

The AVAudioPlayer class provides its own interruption delegate methods, described in AVAudioPlayerDelegate Protocol Reference. Likewise, the AVAudioRecorder class provides its own interruption delegate methods, described in AVAudioRecorderDelegate Protocol Reference. You use similar approaches for the two classes.

When your interruption-started delegate gets called, your audio player is already paused and your audio session is already deactivated. You can provide an implementation such as that shown in Listing 3-1.

Listing 3-1  An interruption-started delegate method for an audio player

- (void) audioPlayerBeginInterruption: (AVAudioPlayer *) player {
    if (playing) {
        playing = NO;
        interruptedOnPlayback = YES;
        [self updateUserInterface];
    }
}

After checking to ensure that the audio player was indeed playing when the interruption arrived, this method updates your app’s state and then updates the user interface. (The system automatically pauses the audio player.)

If a user ignores a phone call, the system automatically reactivates your audio session and your interruption-ended delegate method gets invoked. Listing 3-2 shows a simple implementation of this method.

Listing 3-2  An interruption-ended delegate method for an audio player

- (void) audioPlayerEndInterruption: (AVAudioPlayer *) player {
    if (interruptedOnPlayback) {
        [player prepareToPlay];
        [player play];
        playing = YES;
        interruptedOnPlayback = NO;
    }
}

Responding to a Media Server Reset

The media server provides audio and other multimedia functionality through a shared server process. Although rare, it is possible for the media server to reset while your app is active. Register for the AVAudioSessionMediaServicesWereResetNotification notification to monitor for a media server reset. After receiving the notification, your app needs to do the following:

You can also register for the AVAudioSessionMediaServicesWereLostNotification notification if you want to know when the media server first becomes unavailable. However, most apps only need to respond to the reset notification. Only use the lost notification if the app must respond to user events that occur after the media server is lost, but before the media server is reset.

Providing Guidelines to the User

A user may not want an app to be interrupted by a competing audio session—for instance, when running an audio recorder to capture a presentation.

There is no programmatic way to ensure that an audio session is never interrupted. The reason is that iOS always gives priority to the phone. iOS also gives high priority to certain alarms and alerts—you wouldn’t want to miss your flight now, would you?

The solution to guaranteeing an uninterrupted recording is for a user to deliberately silence their iOS device by taking the following steps:

  1. In the Settings app, ensure that Airplane Mode turned on, for devices that have an Airplane mode.

  2. In the Settings app, ensure that Do Not Disturb is turned on.

  3. In the Calendar app, ensure that there are no event alarms enabled during the planned recording period.

  4. In the Clock app, ensure that no clock alarms are enabled during the planned recording period.

  5. For devices that have a Silent switch (called the Ring/Silent switch on iPhone), do not move the switch during the recording. When you change to Silent mode, an iPhone may vibrate, for example, depending on user settings.

  6. Do not plug in or unplug a headset during recording. Likewise, do not dock or undock the device during recording.

  7. Do not plug the device into a power source during the recording. When an iOS device gets plugged into power, it may beep or vibrate, according to the device and to user settings.

A user guide is a good place to communicate these steps to your users.