Responding to Route Changes
As your app runs, a user might plug in or unplug a headset, or use a docking station with audio connections. iOS Human Interface Guidelines describes how iOS apps should respond to such events. To implement the recommendations, write audio session code to handle audio hardware route changes. Certain types of apps, like games, don’t always have to respond to route changes. However other types of apps, such as media players, must respond to all route changes.
Varieties of Audio Hardware Route Change
An audio hardware route is a wired electronic pathway for audio signals. When a user of an iOS device plugs in or unplugs a headset, the system automatically changes the audio hardware route. Your app can listen for such changes by way of
Figure 5-1 depicts the sequence of events for various route changes during recording and playback. The four possible outcomes, shown across the bottom of the figure, result from actions taken by a property listener callback function that you write.
In the figure, the system initially determines the audio route after your app launches. It continues to monitor the active route as your app runs. Consider first the case of a user tapping a Record button in your app, represented by the “Recording starts” box on the left side of the figure.
During recording, the user may plug in or unplug a headset—see the diamond-shaped decision element toward the lower-left of the figure. In response, the system sends
AVAudioSessionRouteChangeNotification containing the reason for the change and the previous route. Your app should stop recording.
The case for playback is similar but has different outcomes, as shown on the right of the figure. If a user unplugs the headset during playback, your app should pause the audio. If a user plugs in the headset during playback, your app should simply allow playback to continue.
The AddMusic sample code project demonstrates how to implement the playback portion of this behavior.
Responding to Audio Hardware Route Changes
There are two parts to configuring your app to respond to route changes:
Implement methods to be invoked upon a route change.
Register for the
AVAudioSessionRouteChangeNotificationnotification to respond to route changes.
For example, your app receives a notification when a user unplugs the headset during playback. Following Apple guidelines, your app pauses. Your app can then provide a display that prompts the user to continue playing.
When the system sends a route-change notification, it provides the information you need to figure out which action to take. Register for the
AVAudioSessionRouteChangeNotification notification as shown:
NSNotificationCenter *nc [NSNotificationCenter defaultCenter];
After the notification is received, your app calls the method you designate and changes its behavior based on the information contained by the notification. The
AVAudioSessionRouteChangeNotification contains a
userInfo dictionary that describes:
Why the route changed
What the previous route was
The keys for the dictionary are
AVAudioSessionRouteChangePreviousRouteKey. The various reasons why a hardware audio route might have changed—accessed by the
AVAudioSessionRouteChangeReasonKey key—are listed and described in
AVAudioSessionRouteChangeReason. The previous route information—accessed by the
AVAudioSessionRouteChangePreviousRouteKey key—is an object that describes the audio route setting from before the route change.
One reason for the audio hardware route change in iOS is
AVAudioSessionRouteChangeReasonCategoryChange. In other words, a change in audio session category is considered by the system—in this context—to be a route change, and will invoke a route change notification. As a consequence, if your notification response method is intended to respond only to headset plugging and unplugging, it should explicitly ignore this type of route change.
Here’s a practical example. A well-written recorder/playback app sets the audio session category when beginning playback or recording. Because of this, a route-change notification is sent upon starting playback (if you were previously recording) or upon starting recording (if you were previously playing back). Clearly, such an app should not pause or stop each time a user taps Record or Play. To avoid inappropriate pausing or stopping, the method called upon receipt of the notification should branch based on the reason for the route change and simply return if it was a category change. In this case, the category change is from the system’s perspective and not the app’s perspective.