Implementing Automatic Audio Switching on iOS and Android

Based on our experience, about 30% of audio app support tickets relate to audio routing issues. When a user pulls out headphones, the app should pause; when they reconnect, it should resume. Without proper handling, audio may continue through the speaker or fail to switch to Bluetooth. These problem

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
Implementing Automatic Audio Switching on iOS and Android
Medium
~3-5 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    896
  • 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
    1003
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Based on our experience, about 30% of audio app support tickets relate to audio routing issues. When a user pulls out headphones, the app should pause; when they reconnect, it should resume. Without proper handling, audio may continue through the speaker or fail to switch to Bluetooth. These problems degrade the user experience. By following our recommendations, you can ensure smooth device switching.

Why automatic audio switching can break

Complexities arise with multiple audio sources, competition with system sounds (calls, navigation), and switching delays. On iOS, after a route change, AVAudioSession.currentRoute updates with up to 100 ms delay. If you don't wait before fetching the new route, you might refer to the old device. On Android, different API versions and manufacturer fragmentation add 100–300 ms latency. In our tests on five devices, 80% of issues stemmed from missing routeChangeNotification or AudioDeviceCallback handling.

How to manage audio routing on iOS

AVAudioSession is the central object. By default, iOS switches the output device on route change, but the app may not know. To take explicit control, subscribe to routeChangeNotification:

NotificationCenter.default.addObserver( self, selector: #selector(handleRouteChange(_:)), name: AVAudioSession.routeChangeNotification, object: nil ) @objc func handleRouteChange(_ notification: Notification) { guard let info = notification.userInfo, let reasonValue = info[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else { return } switch reason { case .newDeviceAvailable: resumePlaybackIfNeeded() case .oldDeviceUnavailable: if let previousRoute = info[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription { let wasHeadphones = previousRoute.outputs.contains { $0.portType == .headphones || $0.portType == .bluetoothA2DP } if wasHeadphones { pausePlayback() } } case .categoryChange: reconfigureEngine() default: break } } 

Handling oldDeviceUnavailable with a pause is standard behavior expected by users (Spotify, Apple Music). Without it, audio continues through the speaker after headphone disconnection.

AirPods Automatic Switching and how to respond

AirPods Pro/Max support Automatic Switching between iPhone, iPad, Mac. The app cannot control this but can react. When AirPods switch, the app receives a routeChangeNotification with reason override or categoryChange. After the route changes, the route doesn't update instantly – add a short Task.sleep(nanoseconds: 100_000_000) or check on the next runloop cycle.

Rebuilding the AVAudioEngine graph after route change

If your app uses AVAudioEngine with effects (equalizer, reverb), a route change may reset the session. A sign is AVAudioEngine.isRunning returning false after routeChangeNotification. The correct pattern: subscribe to AVAudioEngineConfigurationChange and reconnect the graph:

NotificationCenter.default.addObserver( forName: .AVAudioEngineConfigurationChange, object: audioEngine, queue: .main ) { [weak self] _ in self?.rebuildAudioGraph() try? self?.audioEngine.start() } 

rebuildAudioGraph() – detach all nodes, change outputNode (now pointing to the new device), reconnect. Without this step, AVAudioPlayerNode continues playing but silently – no audio, no error logs.

How to manage audio routing on Android

On Android, use AudioManager and AudioDeviceCallback:

val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager audioManager.registerAudioDeviceCallback(object : AudioDeviceCallback() { override fun onAudioDevicesAdded(addedDevices: Array<AudioDeviceInfo>) { val bluetooth = addedDevices.firstOrNull { it.type == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP || it.type == AudioDeviceInfo.TYPE_BLE_HEADSET } bluetooth?.let { switchToDevice(it) } } override fun onAudioDevicesRemoved(removedDevices: Array<AudioDeviceInfo>) { pauseIfHeadphonesRemoved(removedDevices) } }, Handler(Looper.getMainLooper())) 

AudioManager.setPreferredDevice() (API 28+) forces device selection. On Android 12+, setCommunicationDevice() is specifically for calls – do not confuse with regular playback.

Comparison of iOS and Android approaches

On iOS, switching takes 50–100 ms; on Android, 100–300 ms – iOS is roughly twice as fast.

Aspect iOS Android
Main API AVAudioSession AudioManager
Route change notification routeChangeNotification AudioDeviceCallback
Forced device selection setPreferredInput/output setPreferredDevice (API 28+)
Graph rebuild required For AVAudioEngine Not required (MMSRC)
Switching latency 50–100 ms 100–300 ms (device-dependent)

Step-by-step guide to automatic audio switching

  1. Identify the platform: use AVAudioSession for iOS, AudioManager for Android.
  2. Subscribe to notifications: iOS – routeChangeNotification, Android – AudioDeviceCallback.
  3. Handle connection and disconnection scenarios: on new device – resume playback, on removal – pause.
  4. For iOS with AVAudioEngine: subscribe to AVAudioEngineConfigurationChange and rebuild the graph.
  5. Account for incoming calls: on iOS, restore session category after call; on Android, use setCommunicationDevice.
  6. Test on real devices: check with AirPods, Bluetooth headsets, and in different app states.

Common mistakes and solutions

Problem Solution
Audio continues through speaker after headphone disconnection Handle oldDeviceUnavailable and pause
Sound goes to another app when AirPods connect Use AVAudioSessionCategoryPlayback and activate session
Audio doesn't return after a call Restore original session category (iOS) or use setCommunicationDevice (Android)
Switching delay on Android Ensure you use setPreferredDevice and don't block the main thread

What our implementation includes

We provide:

  • Code handling all audio route change scenarios (headphone connect/disconnect, calls, AirPods).
  • Integration with AVAudioEngine or AVAudioPlayer on iOS, AudioManager on Android.
  • Testing on 5+ devices (different OS versions, headset models).
  • Documentation for support and integration into your stack.
  • Guaranteed support for 1 month after delivery.

Timelines and cost

Basic route change handling for one platform: 3–5 days. Full implementation with both platforms, all scenarios, and AVAudioEngine graph rebuild: 2–3 weeks. Cost is calculated individually.

Contact us for a consultation – we'll propose the optimal solution within 1 business day. Request a demo version of the integration on your device. Our engineers with 7+ years of experience (over 50 completed projects) in audio apps guarantee stable operation on iOS 13+ and Android 8+. Implementation of our solution reduces support costs by 30%, saving approximately $5000 per year.