如何在 iOS 设备上检测耳机(扬声器)的可用性?

Posted

技术标签:

【中文标题】如何在 iOS 设备上检测耳机(扬声器)的可用性?【英文标题】:How to detect ear piece (speaker) availability on iOS devices? 【发布时间】:2016-12-29 06:51:21 【问题描述】:

我想专门在 iPad 上检测是否有可用的耳机。

例如 - 我可以检测 ios 设备是否有使用 AVFoundation,所以有什么方法可以检测耳机的可用性。

【问题讨论】:

【参考方案1】:

1) 如果您想检查设备上是否有耳机(接收器扬声器)

您可以通过简单地识别设备是否为 iPhone 来识别这一点。

UIDevice.current.userInterfaceIdiom == .phone

在 iOS 原型中 AVAudioSessionPortBuiltInReceiver 用于内置 Inreceriver 扬声器。 根据apple's documentation,这仅适用于 iPhone 设备。所以没有必要检查其他任何东西,如果它的 iPhone,你有耳机,如果它不是 iPhone(在 ipad 上)它没有耳机。

2)如果要检查耳机是否连接:

您可以使用共享音频会话的当前路由来检查耳机是否连接: 这是 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;
     

你还应该通过监听路由变化来监控它的状态:

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

这是上述通知设置处理程序的示例代码:

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

【讨论】:

在注意到您对其他答案的评论后,我理解您的问题。所以相应地更新了我的答案。希望这会有所帮助! 我现在面临另一个问题,也许您有任何解决办法:1 - 我插入耳机 -> 我的音频路由更改回调被调用。 2 - 然后我将声音切换到扬声器(无需拔下耳机)-> 调用音频路由更改回调。 3 - 然后我拔下耳机(当声音仍在输出到扬声器时)-> 不调用音频路由更改回调,这似乎是合乎逻辑的。但这是我的问题!所以我的问题是:你有没有办法检测到最后一种情况下耳机被拔掉了? @Nilesh 你在这种情况下找到解决方案了吗。【参考方案2】:

斯威夫特 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

        
    

参考:

苹果文档:https://developer.apple.com/reference/avfoundation/avaudiosessionportdescription/1669281-output_port_types

【讨论】:

我建议使用switch 而不是if/else if/.../else if @Pang Ho Ming 有什么办法可以录制耳机的声音吗?【参考方案3】:

一个班轮Swift 4+解决方案:

检测内置麦克风是否可用

let isMicAvailable: Bool = AVAudioSession.sharedInstance().availableInputs?.first(where:  $0.portType == AVAudioSessionPortBuiltInMic ) != nil

检测耳机(接收器扬声器)是否可用

let isEarPieceAvailable: Bool = AVAudioSession.sharedInstance().currentRoute.outputs.first(where:  $0.portType == AVAudioSessionPortBuiltInReceiver ) != nil

【讨论】:

【参考方案4】:

简短而简单的方法是通过contains 进行检查。

func isHeadphonesConnected() -> Bool
    let routes = AVAudioSession.sharedInstance().currentRoute
    return routes.outputs.contains(where:  (port) -> Bool in
        port.portType == AVAudioSessionPortHeadphones
    )

【讨论】:

其实和 iPhone 一样,我们可以在扬声器和听筒之间切换,但在 iPad 中我们只有扬声器,我担心某些型号是否有像手机一样的听筒扬声器,所以我想检测设备是否有听筒与否。【参考方案5】:

检查

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

【讨论】:

【参考方案6】:

您可以检查内置麦克风是否可用。

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

另一种检查当前设备是否为 iPhone 的方法。

NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:@"iPhone"]) 
    //current device is iPhone.

【讨论】:

以上是关于如何在 iOS 设备上检测耳机(扬声器)的可用性?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取可用输出音频源列表(扬声器、耳机、蓝牙)

在 Mac OS X 上使用 AudioUnit 检测扬声器/耳机

如何检测音频当前是不是正在 Android 手机扬声器上播放?

MPVolumeView 未在 iOS 11 上显示音频路由

联想笔记本插入耳机没声音,如何解决?

如何从电话、电话扬声器、耳机或蓝牙设备切换音频输出