I have spent most of a decade building Android apps for other people. This one I built because every app I tried for my own TV nights was annoying in the same three ways: it buried playback under ads, it could not open half the files already on my phone, and getting anything onto the actual television meant screen mirroring.
So we built ZPlay — one Android app for streaming, Live TV, and the video files you already own. Here is what it does and the engineering decisions behind it.
The problem with "just use ExoPlayer"
ExoPlayer (now media3) is the right default for streaming, and we use it. But it leans on the platform's decoders, and that is where local files fall apart.
Android's MediaCodec only exposes what the manufacturer shipped. Video is usually fine. Audio is not. Dolby Digital (AC-3), Dolby Digital Plus and DTS are licensed codecs and most phones do not include them. Hand ExoPlayer an MKV with a DTS track and it does the correct thing: it plays the video and stays silent, because nothing on the device can decode that audio.
That is the "video plays but no sound" bug everyone eventually files.
Our answer was to stop looking for one engine and route by source instead:
| Source | Engine | Why |
|---|---|---|
| HLS / DASH streams | media3 (ExoPlayer) | Adaptive bitrate, hardware path, battery |
| Local files | libmpv | Handles whatever is actually on the device |
ExoPlayer stays where it is strong. The software decoder only pays its cost on the files that need it, so streaming battery and thermals are unchanged. MKVs with Dolby or DTS just play.
Casting, not mirroring
The second most common complaint about video apps is "casting is broken." Usually it is not — the user is screen mirroring, and the two are completely different:
- Screen mirroring re-encodes the display in real time and pushes it over Wi-Fi. Quality drops, the battery drains, and the phone cannot be used for anything else.
- Casting hands the TV a URL and gets out of the way. The TV pulls the stream. The phone becomes a remote and can be locked.
Two protocols cover most living rooms, and we support both:
- Chromecast / Google Cast — Chromecast, Android TV, Google TV, most modern sets
- DLNA — Samsung, LG and Sony, which is a large installed base that Cast alone never reaches
Supporting both is unglamorous work and it is most of the gap between "casting works" and a one-star review.
Downloads that survive
Third recurring bug in this category: "my download disappeared." Three causes, in order of frequency:
- It was not resumable. The user changed networks and the partial file was thrown away. Range requests are not optional.
- The OS reclaimed it. Anything written to a cache directory is fair game under storage pressure. A download the user deliberately made belongs in persistent storage.
- It died with the app. Long downloads need a foreground service. Users tolerate the notification; they do not tolerate losing 2 GB.
We also let people download a whole season at once, which sounds trivial until you handle partial failure across 30 episodes.
Live TV and the drama library
Beyond files, ZPlay carries free public Live TV playlists with a real tuner — grouped by category and language rather than one endless list — and a library of 175+ Pakistani dramas from HUM TV, GEO and ARY, kept in episode order so a 30-part serial is actually followable.
Episode order and resume sound boring. They are the entire difference between finishing a serial and giving up at episode nine.
The stack
- Flutter for the UI, across phone, tablet and Android TV (with a real D-pad layout, not a stretched phone screen)
- media3 / ExoPlayer for streams
- libmpv for local playback, including Dolby and DTS
- Chromecast + DLNA for the television
- 6 UI languages including RTL
- No ads, no tracking SDKs, no in-app purchases
On the business model
We sell it directly as a signed APK for a one-time $9.99 rather than putting it on Play with a subscription. That is partly principle and partly arithmetic: no store cut is why it can be that cheap, and an app with no ad unit does not need to fight its own user for attention.
It also means we own the update path — new builds ship the day they are ready instead of sitting in review.
What I would like feedback on
If you build video on Android, I would genuinely like to hear how you handled:
- HDR passthrough on devices that claim support and then do not
- Switching audio tracks mid-playback without a visible re-buffer
- Whether you bundled FFmpeg extension renderers instead of a second engine, and what your APK size looked like afterwards
Happy to go deeper on any part of the above in the comments. If you want to look at the app itself, it is at theappsfirm.com/Zplay.






Top comments (0)