Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does AVAudioPlayer keep playing when headphones are unplugged?

Apple indicates that when headphones are unplugged, iOS automatically stops playing.

While this is true when using AVPlayer, it actually does NOT work as expected when using AVAudioPlayer, instead audio keeps continuing to play from the built in speakers.

Link to Apple's site: https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioHardwareRouteChanges/HandlingAudioHardwareRouteChanges.html

like image 305
adamsfamily Avatar asked Jan 20 '26 04:01

adamsfamily


2 Answers

You need to observe the hardware rout change observer and based on callback, You can just stop playing.

Setup your player - play audio (even on silent mode) and silence other music:

let audioSession = AVAudioSession.sharedInstance()
_ = try? audioSession.setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
_ = try? audioSession.setActive(true)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(audioRouteChanged), name: .AVAudioSessionRouteChange, object: nil)


func audioRouteChanged(note: Notification) {
   if let userInfo = note.userInfo {
       if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? Int  {
       if reason == AVAudioSessionRouteChangeReason.oldDeviceUnavailable.hashValue {
       // headphones plugged out
       player.stop()
      }
    }
  }
}

Important: Media playback apps should pause playback if the route change reason is AVAudioSessionRouteChangeReasonOldDeviceUnavailable, but should not if the reason is AVAudioSessionRouteChangeReasonOverride.

I'm not sure but Try this:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSError *setCategoryErr;
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];

    // Detects when the audio route changes (ex: headphones unplugged)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioHardwareRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
    // Don't forget to remove notification in dealloc method!!
}

- (void)audioHardwareRouteChanged:(NSNotification *)notification {
    NSInteger routeChangeReason = [notification.userInfo[AVAudioSessionRouteChangeReasonKey] integerValue];
    if (routeChangeReason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
        // if we're here, The old device is unavailable == headphones have been unplugged, so stop manually!
        [self.player stop];
    }
}
like image 22
Nick Avatar answered Jan 21 '26 17:01

Nick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!