Downloads
Full story: the eight-part downloads deep dive.
What a download actually is
Section titled “What a download actually is”A title is an HLS stream — a playlist pointing at a few thousand 4-second
.ts segments plus one 16-byte AES key. “Downloading a film” means copying
every one of those files to disk and rewriting the playlists to point at the
copies. Each file becomes its own task for the
background_downloader
package; the app’s DownloadManager watches tasks finish and turns that into
progress. Only once the disk proves every file is present does it write the
local playlists and mark the title complete.
Platform realities
Section titled “Platform realities”| Android | iOS | |
|---|---|---|
| Task becomes | a WorkManager job | a background URLSession download |
| Feeding rate | holding queue of 8 | system-managed |
| Keeps going when app backgrounds via | WorkManager + the app’s own foreground service | the system’s background transfer; Dart may not be running |
| Quotas to respect | background job quotas, 6-hour dataSync limit |
resource timeout |
Almost all the complexity exists because phones don’t want apps running in the background, and a two-hour film on a shaky connection outlasts both operating systems’ patience.
Recovery layers
Section titled “Recovery layers”When something goes wrong there are four layers that catch it — package retries, settlement, the stall watchdog, and cold-start reconciliation. The rule everywhere is: re-queue exactly the files missing on disk, never blindly restart the download. User actions: pause, resume, retry, cancel.
State and storage
Section titled “State and storage”Download state lives in more places than you’d expect — Hive
(CacheContentEntity), the disk layout itself, the package database, and
native preferences — plus a status state machine and a startup reconciliation
sequence. Before changing where state lives, read State, storage and
startup and Operating
and extending (logs, adb
recipes, tests, tuning knobs, known limitations).