Implementing Background Audio Playback in Mobile Apps
A call from a client: "Music stops as soon as I lock the screen." This is a typical headache many developers face. Background audio playback is one of the most frequent technical challenges in mobile development. Misconfiguring AVAudioSession on iOS or Audio Focus on Android causes the app to go silent when minimized. We've solved this task more than 50 times and know all the pitfalls. Average integration time — 3 days, and debugging savings thanks to ready-made templates — up to 40% of time. Our engineers test on 15+ real devices, including older models. We've prepared battle-tested code templates for iOS and Android that are already used in production by dozens of apps. One of them is a podcast service with a million-strong audience. A typical solution costs 30–50% less than developing from scratch. Pricing for basic background audio integration starts at $800; adding CarPlay or Android Auto costs an additional $400 each.
How to Configure AVAudioSession for Continuous Playback
Three mandatory steps:
-
Info.plist Background Mode. Add
UIBackgroundModes→audio. Without this, iOS will kill audio a few seconds after entering background. -
AVAudioSession category
.playback. Only this category allows playback with the screen locked and in background..ambientmutes on lock — a common mistake.
func configureAudioSession() { do { let session = AVAudioSession.sharedInstance() try session.setCategory( .playback, mode: .default, options: [.allowBluetooth, .allowAirPlay, .mixWithOthers] ) try session.setActive(true) } catch { print("AudioSession error: \(error)") } } Apple also recommends handling interruptions (documentation). An incoming call deactivates the AVAudioSession. After the call, you need to explicitly restore the session:
NotificationCenter.default.addObserver( forName: AVAudioSession.interruptionNotification, object: nil, queue: .main ) { notification in guard let typeValue = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt, let type = AVAudioSession.InterruptionType(rawValue: typeValue) else { return } switch type { case .began: audioPlayer.pause() case .ended: let shouldResume = (notification.userInfo?[AVAudioSessionInterruptionOptionKey] as? UInt) .flatMap { AVAudioSession.InterruptionOptions(rawValue: $0).contains(.shouldResume) } ?? false if shouldResume { try? AVAudioSession.sharedInstance().setActive(true) audioPlayer.play() } @unknown default: break } } Additionally, listen for AVAudioSession.routeChangeNotification: if headphones are disconnected, pause playback.
Importance of Handling Interruptions on Android
On Android, background playback requires a Foreground Service with type mediaPlayback. Without a Foreground Service, Android will kill the process after a few minutes. Starting from Android 8 (API 26) this is mandatory.
class AudioPlaybackService : Service() { private lateinit var player: ExoPlayer private lateinit var mediaSession: MediaSessionCompat override fun onCreate() { super.onCreate() player = ExoPlayer.Builder(this).build() val notification = buildMediaNotification() startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK) mediaSession = MediaSessionCompat(this, "AudioService") mediaSession.setCallback(mediaSessionCallback) mediaSession.isActive = true } } On Android 14+, you must specify FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK in the manifest and in startForeground. Without the explicit type, you'll get a SecurityException.
Audio Focus must be requested before starting playback:
val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setOnAudioFocusChangeListener { focusChange -> when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> player.pause() AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> player.pause() AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> player.volume = 0.3f AudioManager.AUDIOFOCUS_GAIN -> { player.volume = 1.0f player.play() } } } .build() val result = audioManager.requestAudioFocus(audioFocusRequest) if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { player.play() } Without proper Audio Focus, other apps can override the audio and your player won't recover. ExoPlayer is better than standard MediaPlayer because it handles interruptions twice as fast thanks to built-in focus management. Foreground Service is more reliable than background services — it reduces app termination risk by over 90%.
MediaSession for Lock Screen Controls
Without MediaSession (Android) or MPRemoteCommandCenter (iOS), lock screen and headphone controls won't work. Configuring these components takes about 30% of the development time for background audio. On Android, MediaNotification.Provider creates a notification with buttons, and MediaSession.Callback handles commands. MediaBrowserServiceCompat allows Android Auto integration. On iOS, MPNowPlayingInfoCenter and MPRemoteCommandCenter provide controls; update nowPlayingInfo with every track change, otherwise the progress bar will be inaccurate.
Common Errors and Their Solutions
| Error | Cause | Solution |
|---|---|---|
| Sound disappears after a call (iOS) | Missing setActive(true) |
Add in InterruptionType.ended |
| Notification disappears (Android) | stopForeground(true) removes the notification |
Use stopForeground(false) on pause |
| No sound in Bluetooth headphones | Bluetooth options not specified | On iOS: .allowBluetooth, on Android: AudioAttributes USAGE_MEDIA |
| Interruption not handled (Android) | Missing AudioFocusRequest | Add focus request before start |
Comparison of iOS and Android Approaches
| Parameter | iOS | Android |
|---|---|---|
| Session/Focus | AVAudioSession .playback | AudioFocusRequest |
| Background service | UIBackgroundModes audio | Foreground Service type mediaPlayback |
| Lock Screen | MPNowPlayingInfoCenter + MPRemoteCommandCenter | MediaSession + MediaNotification.Provider |
| Interruptions | AVAudioSession.interruptionNotification | AudioFocusChangeListener |
| Bluetooth | .allowBluetooth | AudioAttributes USAGE_MEDIA |
Our templates reduce development time by 30-50% compared to building from scratch, and we've documented battery savings of up to 25% through optimization.
What Our Work Includes
- Integration of audio engine (ExoPlayer, AVAudioSession, Media3)
- Configuration of Background Mode and Foreground Service
- Implementation of Lock Screen controls (progress bar, control buttons)
- Handling of system interruptions (calls, headphones)
- Testing on 15+ real devices
- Optimization for Android Auto / CarPlay (optional)
- Source code access
- API documentation and integration guide
- Post-release support for 30 days
Contact us for a preliminary assessment of your project — we'll choose the optimal solution. Get a consultation on timeline and cost. Order integration with quality guarantee.
Timeline
Standard implementation of background playback with Lock Screen controls takes 2–3 working days. If support for Android Auto or CarPlay is needed, or a complex lifecycle with multiple content types — up to 5 days. Cost is calculated individually and depends on the scope of work. Pricing for basic background audio integration starts at $800; adding CarPlay or Android Auto costs an additional $400 each.







