The page cannot hand playback to a native app #45
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
For an iOS app that is a web view of the UI but plays in the car.
CarPlay and Android Auto cannot render a web view. Both are template surfaces, and the only audio they will control is the host's own AVPlayer or ExoPlayer. So an app that is "the web UI plus CarPlay" is really "the web UI whose audio engine is native", and the page has no way to give playback away.
web/src/player.tsdrives its media element directly, so inside a native shell there would be two engines on one file, fighting over the same position writes. player.ts is already emphatic about what a stale write costs -- "one left paused in another tab saved its older place as that tab reloaded, over where you had got to since" -- and a backgrounded web view is exactly that tab.What is missing is a bridge: a
web/src/native.tsthat, when the page is running inside a native shell, replaces the element's playback surface (play,pause,src,currentTime,duration,paused,readyState,volume,playbackRate, and the events) with one that forwards to the host and synthesises the events back. player.ts is then not touched at all, because it only ever speaks to the element, and the player bar, the row buttons, the EQ bars and the keyboard shortcuts keep working. Video stays in the page: CarPlay is audio-only, and a native video layer under a web view buys nothing. In a browser nothing installs.Nothing in
src/changes./media/{id}already serves Range throughServeFile, and the position and flags endpoints are what the host writes back through -- the auth layer's own note inweb.rssays it was built so a plain<audio src>would work off cookies alone, which is exactly the property the native player needs.The app lives in its own repo,
ipodderx-ios.Fixed in
9d1492b.web/src/native.tsreplaces the playback surface of the page's media element with one that forwards to a native host and synthesises the events back, soplayer.tsis unchanged and the player bar, row buttons and keyboard shortcuts keep working. Video stays in the page. In a browser nothing installs.Position and read are the host's to write, because a backgrounded web view is frozen and holds a time from minutes ago.
tests/native-bridge.jsholds the two ends together;tests/dom-stub.jsis the stub DOM it shares with page-smoke. It caught a real one straight away: the src setter calledremoveAttribute('src'), which the shim's own override turned into astop()that switched it back off one line after enabling it.Verified end to end on an iOS shell against a fixture daemon: tapping play produced
GET /media/5 -> 206from AVPlayer with the session cookie, and the episode came back read.