How to detect ear piece (speaker) availability on

2020-07-30 02:27发布

问题:

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:

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")
    }
}


回答2:

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



回答3:

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
    })
}


回答4:

Check for

if let availableInputs = AVAudioSession.sharedInstance().availableInputs {
        for route in availableInputs {
            if ( route.portType == AVAudioSessionPortBuiltInMic ) {
                //built-in-mic available
                break;
            }
        }
    }


回答5:

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.
}


回答6:

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