Skingomz/AudioInterruptionHandler.swift
0 → 100644
+72
−0
+153
−16
+11
−0
Loading
Two bugs rather than missing features, both found while auditing what the
app does on iOS beyond playing audio.
Nothing observed the audio session. Downloaded episodes played with the
equalizer or silence skipping go through AVAudioEngine, which does not
pause by itself: taking AirPods out carried on through the loudspeaker,
and after a call the engine sat stopped while the app still believed it
was playing. AudioInterruptionHandler now pauses on an interruption and
resumes afterwards only if playback was running and the system says
resuming is appropriate, and pauses when the output device goes away.
The engine also remembers its last position: once the system stops it,
the player node's render clock is gone and restarting alone would play
silence, so it reschedules from where it was.
Downloads went through URLSession.shared, which iOS suspends about thirty
seconds after the app leaves the foreground — so automatic downloads only
ever finished while the app stayed open. On devices they now run in a
background session the system carries on even after the app is
terminated; the delegate moves the file and records it in the store
itself, since callbacks can arrive during a background relaunch before
any view exists.
macOS keeps a default session: it never suspends the app, so the problem
does not exist there. The Simulator does too, because its transfer daemon
fails every background task with NSURLErrorUnknown (-1) — the same
delegate code on a default session downloads a 21.9 MB episode byte for
byte, which is how it was verified. The background path itself, like the
interruption handling, needs a device: the Simulator can neither place a
call nor take AirPods out.
Co-Authored-By:
Claude Opus 5.5 <noreply@anthropic.com>