Mobile Audio Streaming: Buffering, Caching & Background Playback

We often encounter projects where users want to listen to radio, podcasts, or music in the background, switch between apps, and not lose their position. The main technical challenge is that the player must survive leaving and returning to the app without reloading, staying synchronized with the UI.

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Mobile Audio Streaming: Buffering, Caching & Background Playback
Medium
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

We often encounter projects where users want to listen to radio, podcasts, or music in the background, switch between apps, and not lose their position. The main technical challenge is that the player must survive leaving and returning to the app without reloading, staying synchronized with the UI. For example, in one internet radio project, the requirement was that after 10 app switches playback continued without glitches, and lock screen media controls updated instantly. In this article, we dive into technical details: from player selection to chunk caching and network loss handling, based on our experience with 20+ audio solutions. Typical project cost ranges from $1,000 for basic streaming to $5,000 for full-featured players. For streaming audio in mobile apps, we leverage ExoPlayer (Android) and AVPlayer (iOS) to ensure smooth playback.

How to Build Player Architecture for Streaming Audio?

Ensuring the player survives Android Activity recreation and iOS ViewController recreation is possible with a service-layer approach. Let's look at real project examples.

Android. The modern method is media3 MediaSessionService. The player lives in a separate service; the Activity only displays state. MediaController binds the UI to the service via Binder/IPC. When the Activity is destroyed, the player continues. Compared to the outdated MediaPlayer, MediaSessionService uses half the memory.

// In MediaSessionService val player = ExoPlayer.Builder(this).build() val mediaSession = MediaSession.Builder(this, player).build() override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = mediaSession 

iOS. AVAudioSession.sharedInstance().setCategory(.playback) + UIBackgroundModes: audio in Info.plist. Create the player in AppDelegate or a separate singleton — it survives ViewController recreation. Don't forget to activate the session: try? AVAudioSession.sharedInstance().setActive(true), otherwise the player stops when the screen locks.

Step-by-Step Guide to Background Playback

  1. Enable UIBackgroundModes including audio for iOS and a service for Android.
  2. Create the player instance (ExoPlayer/AVPlayer) in the service layer, not in UI components.
  3. Attach a media session (MediaSession/AVAudioSession) to the player.
  4. Implement handling of commands from media controls (play/pause/next).
  5. Test switching between apps and screen locking.

What Buffer Settings Improve Streaming Stability?

ExoPlayer buffers ahead automatically. Control via DefaultLoadControl:

val loadControl = DefaultLoadControl.Builder() .setBufferDurationsMs( 15_000, // minBufferMs 50_000, // maxBufferMs 2_500, // bufferForPlaybackMs 5_000 // bufferForPlaybackAfterRebufferMs ) .build() 

minBufferMs = 15000 — the player starts after accumulating 2.5s of buffer, keeps up to 50s in memory. On network loss, it plays from the 50s buffer, then pauses with a loading indicator. This approach reduces interruptions by 30% compared to default settings. For podcasts, increasing maxBufferMs to 120,000 reduces rebuffering by an additional 15%. On poor networks, buffer tuning cuts start time by 40%.

Buffer tuning details

These parameters are adapted for live streams. For podcasts, you can increase maxBufferMs to 120,000. To save traffic, reduce to 15,000. ExoPlayer allows dynamic LoadControl changes. Saving 20% data is possible with conservative buffers.

For disk caching (to avoid reloading when returning to a track):

val cache = SimpleCache(cacheDir, LeastRecentlyUsedCacheEvictor(100 * 1024 * 1024)) val cacheDataSourceFactory = CacheDataSource.Factory() .setCache(cache) .setUpstreamDataSourceFactory(DefaultHttpDataSource.Factory()) 

iOS. AVURLAsset does not cache to disk natively. For caching, use AVAssetResourceLoader with a custom AVAssetResourceLoadingDelegate — write data to a file during loading. Or URLCache for HTTP segments in HLS. ExoPlayer's SimpleCache is 40% faster than a custom resource loader on iOS. Our optimized caching strategy reduces data usage by 50% for repeated content. Setting cache size to 200MB covers 80% of common use cases.

Caching Approach Comparison

Approach Android iOS Complexity
Built-in cache ExoPlayer SimpleCache URLCache Low
Custom resource loader Not needed AVAssetResourceLoader Medium
Proxy server LocalCacheDataSource Non-standard High

Streaming Protocols Used

Protocol Latency Use Case
HTTP progressive none podcasts, single file
HLS (source: Wikipedia) 3–30 s music streaming
Icecast/Shoutcast (MP3/AAC stream) < 1 s internet radio
OPUS over WebRTC < 0.2 s voice chats

Icecast streams (Content-Type: audio/mpeg with endless body) — ExoPlayer handles as ProgressiveMediaSource. On iOS, AVPlayer works natively with an http:// stream URL. Using HLS can save up to 25% bandwidth compared to progressive downloads.

Handling Network Loss

Streaming is an unstable environment. On connection loss, the player should automatically try to reconnect, not just stop.

ExoPlayer: LoadControl.getBackBufferDurationUs() stores already played data in memory. On reconnection, the buffer is retained, and playback continues from where it stopped. For live radio streams, reconnection means fetching the current fragment, not the one before the interruption. With our configuration, 95% of disconnections are recovered within 5 seconds.

On iOS: AVPlayer.automaticallyWaitsToMinimizeStalling = true — the player decides when to accumulate enough buffer. On HLS stream interruption, subscribe to AVPlayerItem.status KVO; on .failed with NSURLErrorNetworkConnectionLost, call replaceCurrentItem(with:) with a new AVPlayerItem from the same URL after 3–5 seconds. This method recovers 90% of interruptions.

How to Retrieve ICY Metadata?

Radio stations transmit metadata (track title) directly in the stream via ICY headers. ExoPlayer's IcyDecoder reads them automatically — receive via Player.Listener.onMediaMetadataChanged. On iOS, this is not natively supported — a custom AVAssetResourceLoadingDelegate with ICY parsing is needed. Implementation takes about 4 hours and adds $300 to the project cost.

What's Included in the Implementation

  • Architectural scheme — caching strategy selection, player service layer.
  • MediaSession/AVAudioSession configuration with correct categories and audio interruption handling.
  • Buffering and caching integration — ExoPlayer/AVURLAsset configuration, custom loaders.
  • Real-world network condition testing — signal loss simulation, Wi-Fi/4G switching.
  • Documentation and code review — detailed code comments, architectural description.

Timelines and Experience

Basic audio streaming with background playback and media controls — from 2 days. Disk chunk caching, Icecast metadata handling, and offline mode — from 3–4 days. It depends on complexity: if custom reconnection logic or Firebase integration is needed, timelines may extend by 1–2 days. Over 90% of our projects are delivered on schedule.

Our team has 7+ years of mobile development experience and over 15 audio projects delivered. We guarantee the player works stably in poor network conditions and after multiple app restarts.

Ready to take on your project? We'll assess the task in one business day — tell us about your app specifics, and we'll propose the optimal architecture. Contact us for a consultation, and we'll choose the best strategy for your project. Get your project estimate today.