AVAudioSession - 如何在扬声器和耳机输出之间切换

msm*_*lko 9 avfoundation ios avaudiosession

我试图在通话期间模仿电话应用程序中的行为。您可以轻松地在扬声器或耳机之间切换输出源。我知道我可以在通过调用连接耳机时强制扬声器作为输出:

try! audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)  
try! audioSession.overrideOutputAudioPort(.speaker)  
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时,我看不到任何方法来检测耳机是否仍连接到设备。

我最初认为outputDataSourcesAVAudioSession 会返回所有可能的输出,但它总是返回 nil。

有什么我想念的吗

Moh*_*d S 6

您需要更改 outputDataSources,因为当您覆盖它时,

现在它只包含.Speaker选项

在文档中,您可以找到解决方案,

如果您的应用程序使用 playAndRecord 类别,则使用 AVAudioSession.PortOverride.speaker 选项调用此方法会导致音频路由到内置扬声器和麦克风,而不管其他设置如何。此更改仅在当前路由更改或您使用 AVAudioSession.PortOverride.none 选项再次调用此方法之前保持有效。

因此,音频被路由到内置扬声器,此更改仅在当前路由更改或您再次使用 调用此方法之前保持有效.noneOption

除非将配件插入耳机插孔(这会激活物理开关以将声音定向到耳机),否则无法强制将声音定向到耳机。

所以当你想切换回耳机时,这应该有效。如果没有连接耳机,输出设备将切换到设备顶部的小扬声器输出,而不是大扬声器。

let session: AVAudioSession = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
            try session.overrideOutputAudioPort(AVAudioSession.PortOverride.none)
            try session.setActive(true)
        } catch {
            print("Couldn't override output audio port")
        }
Run Code Online (Sandbox Code Playgroud)

在此处阅读有关此 AVAdioSession/OverrideOutputAudioPort 的信息。

您可以检查耳机是否已连接添加此扩展名,

    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
    }
}
Run Code Online (Sandbox Code Playgroud)

只需使用这行代码

session.isHeadphonesConnected
Run Code Online (Sandbox Code Playgroud)