Are headphones plugged in? iOS7

IosIos7AvaudioplayerAvaudiosessionHeadphones

Ios Problem Overview


Developing an app for an iPhone with audio files that need to be listened too through headphones.

How do I check if headphones aren't plugged in so I can tell the user to plug in headphones.

I have the following code from another thread but the audioSessionGetProperty method is deprecated. Anyone know how to alter the following code to make this work OR have there own code/solution.

Thanks.

- (BOOL)isHeadsetPluggedIn {
    UInt32 routeSize = sizeof (CFStringRef);
    CFStringRef route;


    //Maybe changing it to something like the following would work for iOS7?
    //AVAudioSession* session = [AVAudioSession sharedInstance];
    //OSStatus error = [session setCategory:kAudioSessionProperty_AudioRoute...?
    

    //the line below is whats giving me the warning
    OSStatus error = AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
                                              &routeSize,
                                              &route);
    
    /* Known values of route:
     * "Headset"
     * "Headphone"
     * "Speaker"
     * "SpeakerAndMicrophone"
     * "HeadphonesAndMicrophone"
     * "HeadsetInOut"
     * "ReceiverAndMicrophone"
     * "Lineout"
     */
    
    if (!error && (route != NULL)) {
        
        NSString* routeStr = (__bridge NSString*)route;
        
        NSRange headphoneRange = [routeStr rangeOfString : @"Head"];
        
        if (headphoneRange.location != NSNotFound) return YES;
        
    }
    
    return NO;
}

Ios Solutions


Solution 1 - Ios

This should work, but I cannot test it right now, I'll do in the evening.

- (BOOL)isHeadsetPluggedIn {
    AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
    for (AVAudioSessionPortDescription* desc in [route outputs]) {
        if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])
            return YES;
    }
    return NO;
}

Solution 2 - Ios

Just to extend @Antonio's answer. If you need to detect whether the user has pulled out or plugged in the headphone.

#import <AVFoundation/AVFoundation.h>

// [AVAudioSession sharedInstance]; // @Boris edited: you may need it if there is no `AVAudioSession instance` created before. If doesn't work, uncomment this line.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:)
                                             name:AVAudioSessionRouteChangeNotification
                                           object:nil];
// don't forget to `removeObserver:`

// If the user pulls out he headphone jack, stop playing.
- (void)audioRouteChangeListenerCallback:(NSNotification*)notification
{
    NSDictionary *interuptionDict = notification.userInfo;

    NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];

    switch (routeChangeReason) {
        
        case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
            NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
            NSLog(@"Headphone/Line plugged in");
            break;
        
        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
            NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
            NSLog(@"Headphone/Line was pulled. Stopping player....");
            break;
        
        case AVAudioSessionRouteChangeReasonCategoryChange:
            // called at start - also when other audio wants to play
            NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");
            break;
    }
}

Solution 3 - Ios

Swift 3:

To check if headphones are connected

extension AVAudioSession {
    
    static var isHeadphonesConnected: Bool {
        return sharedInstance().isHeadphonesConnected
    }
    
    var isHeadphonesConnected: Bool {
        return !currentRoute.outputs.filter { $0.isHeadphones }.isEmpty
    }
    
}

extension AVAudioSessionPortDescription {
    var isHeadphones: Bool {
        return portType == AVAudioSessionPortHeadphones
    }
}

Then you can just print("isHeadphones connected: \(AVAudioSession.isHeadphonesConnected)")

Listening to Changes

In Swift 3 the syntax is this:

func handleRouteChange(_ notification: Notification) {
    guard
    let userInfo = notification.userInfo,
    let reasonRaw = userInfo[AVAudioSessionRouteChangeReasonKey] as? NSNumber,
    let reason = AVAudioSessionRouteChangeReason(rawValue: reasonRaw.uintValue)
    else { fatalError("Strange... could not get routeChange") }
    switch reason {
    case .oldDeviceUnavailable:
        print("oldDeviceUnavailable")
    case .newDeviceAvailable:
        print("newDeviceAvailable") 
        if AVAudioSession.isHeadphonesConnected {
             print("Just connected headphones")
        } 
    case .routeConfigurationChange:
        print("routeConfigurationChange")
    case .categoryChange:
        print("categoryChange")
    default:
        print("not handling reason")
    }
}

func listenForNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChange(_:)), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
}

Notice use of:

 if AVAudioSession.isHeadphonesConnected {
    print("Just connected headphones")
 }

Solution 4 - Ios

@Warif's code in Swift 2.0 with little changes ...

func audioRouteChangeListenerCallback (notif: NSNotification){
        let userInfo:[NSObject:AnyObject] = notif.userInfo!
        println("\(userInfo)")
        let routChangeReason = UInt((userInfo[AVAudioSessionRouteChangeReasonKey]?.integerValue)!)
        switch routChangeReason {
        case AVAudioSessionRouteChangeReason.NewDeviceAvailable.rawValue:
            self.println("Headphone/Line plugged in");
            break;
            
        case AVAudioSessionRouteChangeReason.OldDeviceUnavailable.rawValue:
            //If the headphones was pulled move to speaker
            do {
                try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker)
            } catch _ {
            }
            self.println("Headphone/Line was pulled. Stopping player....");
            break;
            
        case AVAudioSessionRouteChangeReason.CategoryChange.rawValue:
            // called at start - also when other audio wants to play
            self.println("AVAudioSessionRouteChangeReasonCategoryChange");
            break;
        default:
            break;
        }
    }

:D

Solution 5 - Ios

In Swift (as of 1.2):

    func headsetPluggedIn() -> Bool {
    let route = AVAudioSession.sharedInstance().currentRoute
    return (route.outputs as! [AVAudioSessionPortDescription]).filter({ $0.portType == AVAudioSessionPortHeadphones }).count > 0
}

Solution 6 - Ios

Swift 3.0 version

  • Method to check if headphones are plugged or any Bluetooth device with audio output connected

    func bluetoothOrHeadphonesConnected() -> Bool {

      let outputs = AVAudioSession.sharedInstance().currentRoute.outputs
      
      for output in outputs{
          
          if output.portType == AVAudioSessionPortBluetoothA2DP ||
             output.portType == AVAudioSessionPortBluetoothHFP ||
             output.portType == AVAudioSessionPortBluetoothLE ||
             output.portType == AVAudioSessionPortHeadphones {
              return true
          }
          
      }
      
      return false 
    

    }

  • It's important to check if the headphones are plugged out while you listen any audio.

private func setupObservers() {

    NotificationCenter.default.addObserver(self, selector: #selector(self.audioRouteChangeListener), name: .AVAudioSessionRouteChange, object: nil)
    
}

func audioRouteChangeListener(notification: Notification) {
    
    guard let audioRouteChangeReason = notification.userInfo![AVAudioSessionRouteChangeReasonKey] as? Int else { return }
    
    switch audioRouteChangeReason {
        
        case AVAudioSessionRouteChangeReason.oldDeviceUnavailable.hashValue:
            //plugged out

        default:
            break
        
    }
    
}

Solution 7 - Ios

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(plugout:) name:AVAudioSessionRouteChangeNotification object:nil];
-(void)plugout:(NSNotification*)notification
{
    isRemovedHeadset = YES;
}

and handle your code using this isRemovedHeadset boolean in your

if (moviePlayer.playbackState == MPMoviePlaybackStatePaused) 
{
    if(isRemovedHeadset)
    {
        isRemovedHeadset = NO;
        [moviePlayer prepareToPlay];
        [moviePlayer play];
        return;
    }
}

Solution 8 - Ios

@Sajjon solution on Swift 5 with RxSwift

func handleRouteChange(_ notification: Notification) {
    guard
        let userInfo = notification.userInfo,
        let reasonRaw = userInfo[AVAudioSessionRouteChangeReasonKey] as? NSNumber,
        let reason = AVAudioSession.RouteChangeReason(rawValue: reasonRaw.uintValue)
        else { fatalError("Strange... could not get routeChange") }
    switch reason {
    case .oldDeviceUnavailable:
        print("oldDeviceUnavailable")
    case .newDeviceAvailable:
        print("newDeviceAvailable")
        if AVAudioSession.isHeadphonesConnected {
            print("Just connected headphones")
        }
    case .routeConfigurationChange:
        print("routeConfigurationChange")
    case .categoryChange:
        print("categoryChange")
    default:
        print("not handling reason")
    }
}

func listenForNotifications() {
    NotificationCenter.default.rx
        .notification(AVAudioSession.routeChangeNotification)
        .subscribe(onNext: { (n) in
            self.handleRouteChange(n)
        })
        .disposed(by: disposeBag)
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Question4GetFullOfView Question on Stackoverflow
Solution 1 - IosAntonio E.View Answer on Stackoverflow
Solution 2 - IosWarif Akhand RishiView Answer on Stackoverflow
Solution 3 - IosSajjonView Answer on Stackoverflow
Solution 4 - IosHusamView Answer on Stackoverflow
Solution 5 - IosMike SpragueView Answer on Stackoverflow
Solution 6 - IosPedro SilvaView Answer on Stackoverflow
Solution 7 - IosHardik MamtoraView Answer on Stackoverflow
Solution 8 - IosmazyView Answer on Stackoverflow