Developing a Music Streaming Mobile App
Music streaming is technically more complex than video in one key aspect—users switch tracks rapidly, expect instant next-track start, listen in background for hours, manage playback from Lock Screen, AirPods, and Apple Watch. Requires deep integration with system audio, not just "AVPlayer plays mp3."
AVAudioSession and Audio Focus
iOS. Proper AVAudioSession setup first:
do {
try AVAudioSession.sharedInstance().setCategory(
.playback,
mode: .default,
options: [.allowBluetooth, .allowAirPlay]
)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
// handle — without this, no background audio
}
.playback category—only one continuing playback on locked screen and background. .allowBluetooth needed for Bluetooth earbuds below A2DP codec. On incoming call, system auto-pauses—listen to AVAudioSession.interruptionNotification and resume correctly after.
Android. AudioManager.requestAudioFocus replaced by AudioFocusRequest (API 26+). Music player must handle three scenarios: full focus loss (incoming call → pause), transient loss (nav voice → duck), focus return (resume). AudioFocusRequest.Builder with OnAudioFocusChangeListener—without this, playback continues over calls.
MediaSession and Lock Screen Controls
Lock Screen and earphone control via MPNowPlayingInfoCenter (iOS) and MediaSession (Android).
iOS: MPRemoteCommandCenter—register handlers for play, pause, next, previous, seek. MPNowPlayingInfoCenter.default().nowPlayingInfo—metadata: title, artist, artwork (as MPMediaItemArtwork), duration, current position. Artwork loads async, update via MPNowPlayingInfoCenter after.
Android: MediaSessionCompat (or MediaSession from Jetpack Media3) + MediaNotification with custom NotificationCompat.MediaStyle. Previous/play/pause buttons via PendingIntent or MediaSession.Callback.
Queue, Playlists, and Shuffle
Playback queue—not just URL list. Account for: shuffle without repeats (Fisher-Yates), history for "back" button, crossfade between tracks.
Crossfade. iOS—two AVPlayer or AVQueuePlayer. AVQueuePlayer.insert(_:after:) queues next; for crossfade—AVAudioMixInputParameters with volume ramping. Alternative: parallel AVAudioPlayer with envelope each.
Android: ExoPlayer Media3 supports MediaItem.ClippingConfiguration for fade points. For crossfade—ConcatenatingMediaSource with custom TransitionListener.
Gapless playback. No pause between tracks. AVQueuePlayer on iOS does gapless natively with correctly attached items. ExoPlayer: ConcatenatingMediaSource gapless when same sample rate. Different formats/rates—possible brief gap on resampling.
Streaming and Offline
Formats. AAC 256 kbps—standard high quality. MP3 320 kbps—compatibility. Lossless: ALAC (iOS, native) or FLAC (Android, ExoPlayer). HLS for adaptive bitrate—useful on unstable networks.
Progressive download. Start playback before full download. AVPlayer does this auto with HTTP URL. ExoPlayer: DefaultDataSource.Factory with caching via SimpleCache. Cached track plays from cache when offline.
Offline library. Download tracks for offline: URLSessionDownloadTask (iOS) with BackgroundURLSession—continues in background. Android: DownloadManager or ExoPlayer DownloadService. DRM-protected—offline license (FairPlay / Widevine), like video.
Storage: tracks in FileManager.default.urls(for: .documentDirectory) on iOS—not cachesDirectory, OS may delete on space shortage. Metadata in CoreData/Room: trackId, localFilePath, downloadDate, expiresAt (for TTL licenses).
Visualizer and Equalizer
Audio visualizer—AVAudioEngine + AVAudioNode on iOS, tap on output node, FFT via vDSP_fft_zrip from Accelerate. Android: Visualizer class from android.media.audiofx, but requires RECORD_AUDIO permission on some devices—non-obvious dependency.
Equalizer: AVAudioUnitEQ (iOS) or Equalizer from android.media.audiofx (Android). Presets: Bass Boost, Vocal, Electronic—preset filter sets. Custom—parametric EQ with user band gains.
Catalog and Recommendations
Search: Elasticsearch with multi_match on title, artist, album. Recommendations for similar artists—collaborative filtering on backend (user listen history) or content-based (audio features: tempo, key, energy via Essentia or AcousticBrainz).
Last.fm API for artist metadata (bio, similar). MusicBrainz for ID and alt metadata.
Timelines
MVP with player, library, Lock Screen Controls: 4–6 weeks. Full streaming service with offline, equalizer, recommendations, licensed DRM: 3–5 months. Cost calculated individually after analyzing requirements.







