Why expo-av Over react-native-track-player
When I needed audio streaming for SanatanApp, the two main options were:
- react-native-track-player — Feature-rich, supports notification controls, queue management. But it's a native module — requires custom dev client, adds build complexity, and is overkill for streaming from static URLs.
- expo-av — Built into Expo managed workflow. Simpler API, supports background playback, works with
expo prebuild. Less features, but fewer headaches.
I chose expo-av because SanatanApp uses Expo managed workflow. Adding a native module would have meant ejecting or setting up a custom dev client — complexity I didn't need for what is essentially "play audio from URL."
The trade-off: no lock-screen controls or notification media controls in v1. For a devotional app where most users play audio while on the app, this was acceptable.
Global Audio Context
Audio state needs to be global — the user might start playing Ramayan on the Home screen, then navigate to Library, then to Settings. The player must persist across all screens.
I use a React Context that wraps the entire app:
The key line is staysActiveInBackground: true. Without this, audio stops when the app goes to background — which is the default behavior on both iOS and Android.
The MiniPlayer Pattern
Every screen in SanatanApp has a persistent MiniPlayer bar at the bottom — showing the current track, a progress bar, and play/pause controls. This is rendered outside the navigation stack, above the bottom tab bar.
This pattern is identical to how Spotify, Apple Music, and YouTube Music handle persistent playback — and users already understand it instinctively.
Progress Persistence with expo-sqlite
When a user is 45 minutes into a 2-hour Ramayan katha and closes the app, they expect to resume from that point tomorrow. I save playback position to SQLite on every status update (throttled to once per 5 seconds):
When loading a track, I check for saved progress and seek to it:
This is a much better UX than most competing apps, which restart audio from the beginning every time.
Public Domain Audio: Zero Cost CDN
SanatanApp streams all audio from Archive.org and other public domain sources. This means:
- $0/month hosting cost — no S3 buckets, no CDN bills, no bandwidth charges
- Legal clarity — public domain recordings have no licensing restrictions
- Reliable infrastructure — Archive.org has been serving files since 1996
The audio source mapping is a simple JSON file:
Adding new audio content is a one-line JSON addition — no code changes, no redeployment needed. The app reads this file at startup and builds the Library screen from it.
The total infrastructure cost for SanatanApp is $0/month. No servers. No databases. No CDN. The only cost is the $25 one-time Google Play developer fee.