Skip to content
AF
Audio Coaching

Headphones out mid-run: route changes on iOS and AUDIO_BECOMING_NOISY on Android

Last verified October 3, 2026 · 6 min read

Sources checked (6) · October 3, 2026
When headphones disconnect, both platforms tell you and both expect you not to carry on through the speaker. Apple's route-change guide says users who disconnect headphones don't want to automatically share what they're listening to, and that apps should automatically pause playback; the signal is routeChangeNotification with the reason oldDeviceUnavailable, posted on a secondary thread. Google documents ACTION_AUDIO_BECOMING_NOISY as a hint sent when a wired headset is unplugged or an A2DP sink disconnects and audio is about to switch to the speaker, and says to register a receiver while you are playing. A workout app makes two decisions here: stop its spoken cues, and usually keep the workout itself running.

Earbuds fall out on runs. A Bluetooth headset drops when the phone is on the far side of the body. A wired pair gets yanked by a cable machine. Each time, the operating system moves audio to the phone's speaker, and the next coaching cue, "you're slowing down, pick it up", plays out loud on a train platform.

Both platforms tell you when this happens and both expect you not to carry on out loud. A workout app has a second question a music player does not: the audio should stop, but should the workout?

iOS: routeChangeNotification and oldDeviceUnavailable#

Apple's Responding to audio route changes article defines the event: "A route change occurs when the system adds or removes an audio input or output. Route changes occur for several reasons, including a user plugging in a pair of headphones, connecting a Bluetooth LE headset, or unplugging a USB audio interface."

It also states the expectation in plain terms: "When users connect a pair of wired or wireless headphones, they're implicitly indicating that audio playback should continue, but privately. They expect an app that's currently playing media to continue playing without pause. However, when users disconnect their headphones, they don't want to automatically share what they're listening to with others. Applications should respect this implicit privacy request and automatically pause playback when users disconnect their headphones."

The notification is routeChangeNotification. Its user info "contains the AVAudioSessionRouteChangeReasonKey and AVAudioSessionRouteChangePreviousRouteKey keys." The reason you care about is oldDeviceUnavailable, "A value that indicates that the previous audio output path is no longer available." Its opposite, newDeviceAvailable, means "a user action, such as plugging in a headset, has made a preferred audio route available."

One line on the notification page decides how you write the handler: "The system posts this notification on a secondary thread." The interruption notification is posted on the main thread; this one is not. Hop to the main actor before touching the cue scheduler or the UI.

let privatePorts: Set<AVAudioSession.Port> = [.headphones, .bluetoothA2DP, .bluetoothLE]

func handleRouteChange(_ notification: Notification) {
    guard let info = notification.userInfo,
          let raw = info[AVAudioSessionRouteChangeReasonKey] as? UInt,
          let reason = AVAudioSession.RouteChangeReason(rawValue: raw),
          reason == .oldDeviceUnavailable,
          let previous = info[AVAudioSessionRouteChangePreviousRouteKey]
              as? AVAudioSessionRouteDescription,
          previous.outputs.contains(where: { privatePorts.contains($0.portType) })
    else { return }

    Task { @MainActor in cueScheduler.headphonesRemoved() }
}

Apple's article checks only .headphones, which its AVAudioSession.Port reference describes as "An output to wired headphones." Wireless earbuds report other ports: .bluetoothA2DP is "An output to a Bluetooth A2DP device" and .bluetoothLE "An output to a Bluetooth Low Energy (LE) device." Copy Apple's check unchanged and your handler ignores every wireless headset.

Apple also documents prefersInterruptionOnRouteDisconnect, available from iOS 17: "A Boolean value that indicates whether the system interrupts the audio session when the active route disconnects." Apple states "The default value is true." So on current systems a disconnect can reach you as an interruption as well as a route change; a handler written for only one of the two will miss cases. The interruption side is on the interruptions page.

Apple's Playing audio guidelines put the expectation in one sentence: "when disconnecting headphones, they expect playback to pause immediately."

Android: ACTION_AUDIO_BECOMING_NOISY#

Google's AudioManager reference documents ACTION_AUDIO_BECOMING_NOISY as a "Broadcast intent, a hint for applications that audio is about to become 'noisy' due to a change in audio outputs. For example, this intent may be sent when a wired headset is unplugged, or when an A2DP audio sink is disconnected, and the audio system is about to automatically switch audio route to the speaker." Google continues: "Applications that are controlling audio streams may consider pausing, reducing volume or some other action on receipt of this intent so as not to surprise the user with audio from the speaker." The constant value is android.media.AUDIO_BECOMING_NOISY.

Google's Handling changes in audio output guide says to "create a BroadcastReceiver that listens for this intent whenever you're playing audio," and to "Register the receiver when you begin playback, and unregister it when you stop."

private class BecomingNoisyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) {
            cueScheduler.headphonesRemoved()
        }
    }
}

private val noisyFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)

The same guide draws a line that a workout app falls across: "Users usually expect apps that include a music player with onscreen playback controls to pause playback in this case. Other apps, like games that don't include controls, should keep playing." A coaching app has controls, but the thing playing is a schedule, not a track.

On a watch, the Wear OS guide handles the Bluetooth case with registerAudioDeviceCallback rather than this broadcast; that is on the watch audio page.

Two decisions, not one#

What follows is our judgement, built on the platform behaviour above.

The audio decision follows the platforms: stop speaking out loud. Neither company's guidance supports carrying on through the speaker after headphones are pulled, and Apple frames it as a privacy expectation.

The workout decision is yours, and it is usually the opposite. The person lost an earbud; they did not stop running. Pausing the workout clock because the audio route changed corrupts the session record: a run with a three-minute hole that never happened.

What changedAudioWorkout clockTell the user by
Headphones removed mid-intervalStop spoken cuesKeep runningA haptic and the on-screen state
Headphones reconnectedResume cues at the next boundaryUnchangedThe next cue
Bluetooth drops and reconnects within secondsSkip cues during the gap; do not replay themUnchangedNothing, if no cue fell in the gap
The user taps pauseStopPauseThe pause UI

The third row is where most implementations go wrong: they queue the cues that fell in the gap and play them all on reconnect. A burst of three stale cues is worse than missing one.

Speaker as a deliberate choice#

Some users train without headphones on purpose: a phone on the floor beside a mat, a tablet propped against a wall at home. For them, speaker output is the intended route. Our judgement: make speaker cues an explicit setting, ask once when a workout starts with no headphones connected, and only then treat a disconnect as not worth pausing for. The platforms' default expectation is privacy; an opt-in is how a user overrides it.

Monday morning#

Register the route-change observer on iOS and the becoming-noisy receiver on Android for the lifetime of the workout. In both handlers, stop spoken cues, keep the workout clock running, and fire a haptic. Make sure no cue that fell inside a disconnect gap is replayed later. Then pull an earbud mid-interval on each platform, once wired and once Bluetooth.

Frequently asked questions

Should a workout app keep speaking cues through the phone speaker after headphones disconnect?
Not unless the user opted in. Apple's route-change guide frames a headphone disconnect as an implicit privacy request and says apps should automatically pause playback, and Google's guide warns that audio rerouted to the speaker can be a noisy surprise. Our judgement is to stop spoken cues, fire a haptic, and keep the workout clock running, because the person lost an earbud, not their workout. Users who train without headphones on purpose can turn on speaker cues as an explicit setting.
Which thread does AVAudioSession routeChangeNotification arrive on?
A secondary thread. Apple's routeChangeNotification page states that the system posts this notification on a secondary thread, unlike the interruption notification, which Apple documents as posted on the main thread. Hop to the main actor before touching your cue scheduler or the interface. The notification's user info carries AVAudioSessionRouteChangeReasonKey and AVAudioSessionRouteChangePreviousRouteKey, and the previous route is where you check which outputs were just lost.
What is ACTION_AUDIO_BECOMING_NOISY and when is it sent?
A broadcast intent Android sends just before audio moves to the speaker. Google's AudioManager reference describes it as a hint that audio is about to become noisy due to a change in audio outputs, for example when a wired headset is unplugged or an A2DP audio sink is disconnected, and suggests pausing, reducing volume or some other action so as not to surprise the user. Google's output guide says to register a BroadcastReceiver for it when playback begins and unregister it when playback stops.

All 42 questions in Audio Coaching →

Keep reading

Elsewhere on the site

Pages that share this one’s concepts and sources, from other sections.

Next steps

Was this page useful?

Independent comparison, last reviewed October 3, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.

← All audio coaching · by AIFitnessAPI