---
title: "Headphones out mid-run: route changes on iOS and AUDIO_BECOMING_NOISY on Android"
canonical: "https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change"
cluster: "Audio Coaching"
primary_query: "headphones disconnected during workout audio"
last_reviewed: "2026-10-03"
description: "oldDeviceUnavailable on iOS and ACTION_AUDIO_BECOMING_NOISY on Android: stop speaking out loud when earbuds drop, but keep the workout clock running."
publisher: "AIFitnessAPI — independent, not sponsored"
cite_as: "\"Headphones out mid-run: route changes on iOS and AUDIO_BECOMING_NOISY on Android\", AIFitnessAPI, https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change"
---

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

> 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.

- Canonical: https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change
- Last reviewed: 2026-10-03
- Publisher: AIFitnessAPI (https://aifitnessapi.com) — independent, not sponsored
- Cite as: "Headphones out mid-run: route changes on iOS and AUDIO_BECOMING_NOISY on Android", AIFitnessAPI, https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change

---

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](https://developer.apple.com/documentation/avfaudio/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`](https://developer.apple.com/documentation/avfaudio/avaudiosession/routechangenotification). Its user info "contains the AVAudioSessionRouteChangeReasonKey and AVAudioSessionRouteChangePreviousRouteKey keys." The reason you care about is [`oldDeviceUnavailable`](https://developer.apple.com/documentation/avfaudio/avaudiosession/routechangereason/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.

```swift
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`](https://developer.apple.com/documentation/avfaudio/avaudiosession/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](/audio-coaching/audio-interruptions-during-workout-ios).

Apple's [Playing audio guidelines](https://developer.apple.com/design/human-interface-guidelines/playing-audio) put the expectation in one sentence: "when disconnecting headphones, they expect playback to pause immediately."

## Android: ACTION_AUDIO_BECOMING_NOISY

Google's [AudioManager reference](https://developer.android.com/reference/android/media/AudioManager) 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](https://developer.android.com/media/platform/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."

```kotlin
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](/audio-coaching/wear-os-watchos-workout-audio).

## 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 changed | Audio | Workout clock | Tell the user by |
| --- | --- | --- | --- |
| Headphones removed mid-interval | Stop spoken cues | Keep running | A [haptic](/accessibility/haptics-when-audio-is-busy) and the on-screen state |
| Headphones reconnected | Resume cues at the next boundary | Unchanged | The next cue |
| Bluetooth drops and reconnects within seconds | Skip cues during the gap; do not replay them | Unchanged | Nothing, if no cue fell in the gap |
| The user taps pause | Stop | Pause | The 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.

## Sources

- [developer.apple.com/documentation/avfaudio/responding-to-audio-route-changes](https://developer.apple.com/documentation/avfaudio/responding-to-audio-route-changes) — route change model; pause on disconnect (checked 2026-10-03)
- [developer.apple.com/documentation/avfaudio/avaudiosession/routechangenotification](https://developer.apple.com/documentation/avfaudio/avaudiosession/routechangenotification) — user info keys; secondary thread (checked 2026-10-03)
- [developer.apple.com/documentation/avfaudio/avaudiosession/prefersinterruptiononroutedisconnect](https://developer.apple.com/documentation/avfaudio/avaudiosession/prefersinterruptiononroutedisconnect) — iOS 17 preference, default true (checked 2026-10-03)
- [developer.apple.com/documentation/avfaudio/avaudiosession/port](https://developer.apple.com/documentation/avfaudio/avaudiosession/port) — headphones, bluetoothA2DP and bluetoothLE port types (checked 2026-10-03)
- [developer.android.com/reference/android/media/AudioManager](https://developer.android.com/reference/android/media/AudioManager) — ACTION_AUDIO_BECOMING_NOISY (checked 2026-10-03)
- [developer.android.com/media/platform/output](https://developer.android.com/media/platform/output) — registering the becoming-noisy receiver (checked 2026-10-03)

## FAQ

### 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.

[Permalink](https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change#faq-1)

### 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.

[Permalink](https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change#faq-2)

### 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.

[Permalink](https://aifitnessapi.com/audio-coaching/headphones-disconnect-route-change#faq-3)
