---
title: "Testing workout audio cues: calls, Siri, Bluetooth and the podcast that never resumes"
canonical: "https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues"
cluster: "Audio Coaching"
primary_query: "testing workout audio cues"
last_reviewed: "2026-10-03"
description: "A device test matrix for workout audio cues on iOS and Android, built from documented events: calls, Siri, podcasts, unplugged earbuds, Android 15 focus."
publisher: "AIFitnessAPI — independent, not sponsored"
cite_as: "\"Testing workout audio cues: calls, Siri, Bluetooth and the podcast that never resumes\", AIFitnessAPI, https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues"
---

# Testing workout audio cues: calls, Siri, Bluetooth and the podcast that never resumes

> Audio cue bugs live in transitions a desk test never triggers, so the test plan is a list of documented platform events caused on purpose, each with an expected result from the platform's documentation. On iOS that means a screen lock with music playing, a podcast app playing, an incoming call in both banner and full-screen styles, Siri listening, which Apple documents as setting promptStyle to none, headphones being removed, and Apple's own Reset Media Services item in the Developer menu of Settings. On Android it means a background cue from an app targeting API level 35, speech content playing, a phone call, headphones removed and a missing TTS voice. Keep the cue decision a pure function you unit-test, and test the delivery on devices.

- Canonical: https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues
- Last reviewed: 2026-10-03
- Publisher: AIFitnessAPI (https://aifitnessapi.com) — independent, not sponsored
- Cite as: "Testing workout audio cues: calls, Siri, Bluetooth and the podcast that never resumes", AIFitnessAPI, https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues

---

Audio cue bugs do not live in the cue. They live in transitions: the screen locking, a call arriving, Siri listening, a podcast that should pause and resume, an earbud falling out, an Android build targeting a newer API level. A desk test with the screen on and nothing else playing triggers none of them. So the test plan is a list of documented platform events, each caused on purpose, each with an expected result taken from the platform's own documentation.

This page is that list. Each row links to the page that explains the behaviour.

## What can be unit-tested, and what cannot

Split the cue system in two. The decision ("given the workout time, the prompt style, whether focus was granted and whether headphones are connected, should this cue be speech, a tone, a haptic or nothing?") is a pure function. Test it exhaustively in your normal suite, alongside the rest of [test](/test). The delivery, meaning the session, focus, route and engine, can only be tested on a device, because every interesting input comes from the operating system.

```swift
enum CueOutput { case speech, tone, haptic, skip }

func output(promptStyle: AVAudioSession.PromptStyle,
            headphonesConnected: Bool,
            speakerOptIn: Bool) -> CueOutput {
    switch promptStyle {
    case .none:   return .haptic
    case .short:  return .tone
    default:      return (headphonesConnected || speakerOptIn) ? .speech : .haptic
    }
}
```

The mapping from `promptStyle` comes from Apple's descriptions of the three styles, set out on [the AVSpeechSynthesizer page](/audio-coaching/avspeechsynthesizer-workout-cues). The headphones branch is our judgement from [the route-change page](/audio-coaching/headphones-disconnect-route-change).

## The iOS device matrix

| Cause this | How | Expected, per Apple | Assert in your app |
| --- | --- | --- | --- |
| Screen lock with music playing | Start music, start a workout, lock | `playback` audio continues when the screen locks, with `audio` in UIBackgroundModes | Every cue plays; music ducks and returns ([background audio](/audio-coaching/background-audio-workout-app-ios)) |
| A podcast is playing | Play a podcast app, then trigger a cue | `interruptSpokenAudioAndMixWithOthers` pauses spokenAudio sessions while you are active; the system resumes them after you deactivate | The podcast resumes after each cue ([duckOthers](/audio-coaching/avaudiosession-duckothers-workout-cues)) |
| Incoming call, banner style | Call the device | With `setPrefersNoInterruptionsFromSystemAlerts(true)`, the session is interrupted only if the user accepts | Cues pause only on accept |
| Incoming call, full-screen style | Switch the call display style, call again | The preference "has no effect"; the system interrupts the session | Speech suspended; workout clock unaffected ([interruptions](/audio-coaching/audio-interruptions-during-workout-ios)) |
| Siri listening | Invoke Siri mid-interval | `promptStyle` is `.none` while another session uses the microphone | No speech or tone; haptic fires |
| A voice call in progress | Join a call, then trigger a cue | `promptStyle` is `.short` "when a voice call is active" | A tone, not words |
| Wired or Bluetooth headphones removed | Unplug or power off mid-cue | `routeChangeNotification` with `oldDeviceUnavailable`, posted on a secondary thread | Speech stops; workout continues; no stale cues on reconnect |
| Media services reset | Settings, then Developer, then Reset Media Services | `mediaServicesWereResetNotification`; reinitialize audio objects and reset category, options and mode | Next cue plays without restarting the app |

The last row is a test Apple documents directly. The [`mediaServicesWereResetNotification`](https://developer.apple.com/documentation/avfaudio/avaudiosession/mediaserviceswereresetnotification) page: "You can trigger a media server reset by choosing the "Reset Media Services" selection under the Developer menu in the iOS Settings app. Using this utility helps to ensure that your app responds appropriately if media services were reset." Most audio code has never been through it.

## The Android device matrix

| Cause this | How | Expected, per Google | Assert in your app |
| --- | --- | --- | --- |
| Background cue, app targeting API level 35 or higher | Screen off, no foreground service | `requestAudioFocus` returns `AUDIOFOCUS_REQUEST_FAILED` | With the workout's foreground service running, the cue plays ([Android 15](/audio-coaching/audiofocus-request-failed-android-15)) |
| Music playing | Play music, trigger a cue | On Android 8.0 and higher, a `MAY_DUCK` request ducks the music automatically and restores it on abandon | Music ducks and returns ([MAY_DUCK](/audio-coaching/android-audio-focus-may-duck)) |
| Speech content playing | Play a podcast or audiobook app | No automatic ducking of `CONTENT_TYPE_SPEECH`; that app's listener gets `AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK` | Whatever the other app does, your cue still plays and focus is abandoned |
| Phone call | Call the device mid-workout | Focus may be locked; `requestAudioFocus` returns `AUDIOFOCUS_REQUEST_FAILED` | Cue skipped, haptic fires, not replayed after the call |
| Headphones removed | Unplug, or disconnect a Bluetooth headset | `ACTION_AUDIO_BECOMING_NOISY` broadcast | Speech stops; workout continues |
| TTS voice missing | Set a language with no installed voice | `setLanguage` returns `LANG_MISSING_DATA` or `LANG_NOT_SUPPORTED` | User told before the workout starts ([TextToSpeech](/audio-coaching/texttospeech-workout-cues-android)) |
| Wear OS watch, no earbuds | Run with nothing paired | Media should play only with a suitable output; short cues may use the speaker | Cues play on the speaker or as haptics; media offers Bluetooth settings ([watch audio](/audio-coaching/wear-os-watchos-workout-audio)) |

Two Android rows depend on the OS version, so run them on at least one device below Android 12 and one on Android 12 or later: Google's guide says audio focus is "not managed by the system" before Android 12, and the forced fade-out and call mute arrive with it.

## Logging that makes field reports useful

The matrix catches what you can cause. Field reports catch the rest, but only if the log has the inputs. Our judgement on what to log per cue, on both platforms:

- scheduled time and actual time played, or why it was skipped
- the focus request result on Android, or whether activation threw on iOS
- `promptStyle` on iOS
- the current output route
- app state: foreground or background, and on Android whether the foreground service was running

With those five fields, most "the coach went quiet" reports can be matched to a row in one of the tables above.

## Who should run it

Run the matrix on real devices, with the screen locked, for a full workout, not in short bursts with the screen on. That is our recommendation, not something either platform states. The device-lab mechanics are in [device lab and CI](/test/device-lab-and-ci); watch-specific setup is in [testing watch apps](/watch-apps/testing-watch-apps); and accessibility testing of the same flows, including a screen reader talking over your cues, is in [testing accessibility](/accessibility/testing-accessibility-fitness-app).

## Monday morning

Extract the cue decision into a pure function and give it a table-driven test. Print the two device matrices and walk one device through each before the next release, starting with Reset Media Services on iOS and a screen-off cue on an Android build targeting API level 35. Add the five log fields. Then hand the matrix to whoever does release testing, because none of these rows will ever fail on a developer's desk.

## Sources

- [developer.apple.com/documentation/avfaudio/avaudiosession/mediaserviceswereresetnotification](https://developer.apple.com/documentation/avfaudio/avaudiosession/mediaserviceswereresetnotification) — Reset Media Services test utility (checked 2026-10-03)
- [developer.apple.com/documentation/avfaudio/avaudiosession/promptstyle-swift.enum/none](https://developer.apple.com/documentation/avfaudio/avaudiosession/promptstyle-swift.enum/none) — none style while Siri recognizes speech (checked 2026-10-03)
- [developer.apple.com/documentation/avfaudio/avaudiosession/setprefersnointerruptionsfromsystemalerts(_:)](https://developer.apple.com/documentation/avfaudio/avaudiosession/setprefersnointerruptionsfromsystemalerts%28_:%29) — banner versus full-screen call styles (checked 2026-10-03)
- [developer.android.com/media/optimize/audio-focus](https://developer.android.com/media/optimize/audio-focus) — Android 15 focus restriction; Android 12 system-managed focus; speech not ducked (checked 2026-10-03)
- [developer.android.com/reference/android/speech/tts/TextToSpeech](https://developer.android.com/reference/android/speech/tts/TextToSpeech) — language support codes (checked 2026-10-03)

## FAQ

### How do I test my iOS app's response to a media services reset?

Use the switch Apple documents for it. Apple's mediaServicesWereResetNotification page says you can trigger a media server reset by choosing Reset Media Services under the Developer menu in the iOS Settings app, and that doing so helps ensure your app responds appropriately. Apple says to respond by reinitializing your audio objects and resetting the session's category, options and mode, and notes you don't need to re-register for audio session notifications. Run it mid-workout and confirm the next cue plays without restarting the app.

[Permalink](https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues#faq-1)

### What should I test before shipping workout audio cues on an app targeting Android 15?

A cue with the screen off. Google documents that an app targeting Android 15 or higher cannot request audio focus unless it's the top app or running a foreground service, and gets AUDIOFOCUS_REQUEST_FAILED otherwise, so a screen-off cue without a running foreground service fails silently. Test it with and without your workout's foreground service, log every focus result with the app state, and also test a phone call, which locks focus and produces the same return value for a different reason.

[Permalink](https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues#faq-2)

### Which audio events should a workout app test on a real device before release?

Our list, built from what the platforms document: a full workout with the screen locked and music playing; a podcast app playing, which should pause and resume around each cue; an incoming call, in both call display styles on iOS; Siri or another microphone user mid-interval; wired and Bluetooth headphones removed mid-cue; and, on Android, a device below Android 12 and one at Android 12 or later, because Google documents that audio focus is only managed by the system from Android 12.

[Permalink](https://aifitnessapi.com/audio-coaching/testing-workout-audio-cues#faq-3)
