I want to detect specially on iPad's if there is ear piece available or not.
For example - I can detect if the iOS device hasTourch or not using AVFoundation so is there any way to detect ear piece availability.
I want to detect specially on iPad's if there is ear piece available or not.
For example - I can detect if the iOS device hasTourch or not using AVFoundation so is there any way to detect ear piece availability.
1) If you want to check if Ear piece (Receiver speaker) is available on device
You can identify this by simply identifying if Device is iPhone.
UIDevice.current.userInterfaceIdiom == .phone
in iOS prottype AVAudioSessionPortBuiltInReceiver
is there for builtInreceriver speaker.
and according to apple's documentation, This is available only on iPhone device. So there is no need to check for anything else, If its iPhone, You have Ear piece and if its not iPhone (on ipad) it don't have ear piece.
2) If you want to check if head phone is connected or not:
You can use currentroute of share audio session to check if headset is connected or not: here is sample function in swift 3.0
func IsHeadSetConnected() -> Bool{
let route = AVAudioSession.sharedInstance().currentRoute;
for desc in route.outputs
{
let portType = desc.portType;
if (portType == AVAudioSessionPortHeadphones)
{
return true;
}
}
return false;
}
You should also monitor its status by listening for route change:
NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChange(_:)), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
here is sample code for handler of notification setup above:
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("headset/line plugged in")
case .routeConfigurationChange:
print("headset pulled out")
case .categoryChange:
print("Just category change")
default:
print("not handling reason")
}
}
Swift 3:
import AVFoundation
let currentRoute = AVAudioSession.sharedInstance().currentRoute
for description in currentRoute.outputs {
if description.portType == AVAudioSessionPortLineOut {
}else if description.portType == AVAudioSessionPortHeadphones {
}else if description.portType == AVAudioSessionPortBluetoothA2DP{
}else if description.portType == AVAudioSessionPortBuiltInReceiver{
}else if description.portType == AVAudioSessionPortBuiltInSpeaker{
}else if description.portType == AVAudioSessionPortHDMI{
}else if description.portType == AVAudioSessionPortAirPlay{
}else if description.portType == AVAudioSessionPortBluetoothLE{
}
}
Reference:
Apple document: https://developer.apple.com/reference/avfoundation/avaudiosessionportdescription/1669281-output_port_types
The short and simplest way is to check via contains
.
func isHeadphonesConnected() -> Bool{
let routes = AVAudioSession.sharedInstance().currentRoute
return routes.outputs.contains(where: { (port) -> Bool in
port.portType == AVAudioSessionPortHeadphones
})
}
Check for
if let availableInputs = AVAudioSession.sharedInstance().availableInputs {
for route in availableInputs {
if ( route.portType == AVAudioSessionPortBuiltInMic ) {
//built-in-mic available
break;
}
}
}
You can check if built-in-mic is available.
var isMicAvailable = false
if let availableInputs = AVAudioSession.sharedInstance().availableInputs {
for route in availableInputs {
if ( route.portType == AVAudioSessionPortBuiltInMic ) {
//built-in-mic available
isMicAvailable = true
break;
}
}
}
print("current device has mic - \(isMicAvailable)")
Another way to to check if current device is iPhone.
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:@"iPhone"]) {
//current device is iPhone.
}
One liner Swift 4+ solution to:
Detect if built-in-mic is available
let isMicAvailable: Bool = AVAudioSession.sharedInstance().availableInputs?.first(where: { $0.portType == AVAudioSessionPortBuiltInMic }) != nil
Detect if the Ear piece (Receiver speaker) is available
let isEarPieceAvailable: Bool = AVAudioSession.sharedInstance().currentRoute.outputs.first(where: { $0.portType == AVAudioSessionPortBuiltInReceiver }) != nil