Are headphones plugged in? iOS7
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;
}
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;
}
}
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")
}
@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
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
}