← Pengyu Jie · Portfolio Contact

Resonova · Engineering note · September 2026

One authority decides what plays next

Resonova turns a playlist into a hosted radio show: two AI hosts talk between the real songs. On Android the hard part isn't generating the show. It is playing it in the right order — song, then commentary, then the next song — while Spotify, the network and the phone each have their own idea of what is happening.

The problem

A cast mixes two kinds of audio that live in different places. The commentary is Resonova's own audio. The songs are played by Spotify, a separate app that Resonova can only command and observe — through Spotify's App Remote SDK on the phone, or its Web API over the network.

Four parties can disagree at any moment:

Early versions split the decision between two runtimes: a web view that ran the show while visible, and native code that took over in the background. Each could advance the show. The symptoms were what you'd expect from two writers on one cursor: the two runtimes racing to move the show on, commentary and music colliding, and timers that starved when the phone went into Doze.

The decision

One authority: a single native conductor, running in an Android foreground service, owns the show's timeline. The UI sends commands and shows state. It never advances the show by itself.

Listener → command → Conductor (decides) → Spotify / commentary player (act) → reports → Conductor (observes) → UI (shows)

The service keeps running across foreground, background, lock screen and Doze, so the show never depends on the screen being on. Android's media session is the system's view of that one timeline — lock screen, notification and headset buttons all talk to the same conductor.

The rules that keep it honest

  1. Spotify reports facts; it never decides Spotify's state tells the conductor what happened to a song. Only the conductor decides what happens next.
  2. Every result says how it is known Instead of a bare paused flag, results are PauseAccepted, ObservedIdle, Unknown or NotEnded, each tagged with where it came from (App Remote or Web API). Unknown is never treated as silence.
  3. Uncertainty never blocks the show A result the app can't determine changes how Spotify is cleaned up, not whether the cast moves on. The one exception: if every way to see Spotify is gone, the show stops and the listener decides — because moving on might start commentary over music.
  4. No second clock A song ends when Spotify says it moved off, cleared or restarted it — not when a timer thinks it should have. The app steps in only when Spotify goes quiet, with one coarse watchdog whose job is to ask, not to guess.
  5. Commentary never plays over music If music is audible and the pause isn't confirmed, that commentary is skipped and the show moves on. Skip, never block.
  6. Own the show, report the rest Where Spotify plays, whether the network is real, and the listener's sign-in belong to someone else. When one of them breaks the show, the player says so in one plain sentence — what happened, what the app is still doing, what the listener can do — instead of a silent retry.

What I rejected

What broke, and what it taught me

The rules came from bugs, not from a whiteboard. Two stand out:

Bugs like these live in the gaps between Spotify, Android's power management and the network, so unit tests alone don't catch them. Playback changes are verified on a physical phone before they ship.

Result

One place decides, so there is one place to reason about. Casts keep playing in the background, on the lock screen and through Doze; commentary and music don't collide; and when something outside the app breaks, the listener is told the truth instead of watching a spinner.

Resonova is a private beta (Kotlin / Android, Python / FastAPI, Gemini, Spotify). Written by Pengyu Jie.

Back to the portfolio Request access