在连接airpods时,在将音频切换到扬声器后,routeChangeNotification检测到newDeviceAvailable

时间:2019-03-27 20:54:14

标签: swift iphone avaudioplayer avaudiosession airpods

当我将airpods连接到iphone并尝试将音频覆盖到扬声器时,音频默认返回给airpods。使用其他任何蓝牙设备或其他音频选项都不会出现此问题。连接airpods时如何使扬声器的输出杆固定?

这是我设置音频会话的方式:

   var err: Error? = nil
            let session = AVAudioSession.sharedInstance()
            do {
                try session.setCategory(AVAudioSession.Category.playAndRecord, mode: .voiceChat, options: [.allowBluetooth, .allowBluetoothA2DP, .mixWithOthers])
            } catch {
                NSLog("Unable to change audio category because : \(String(describing: err?.localizedDescription))")
                err = nil
            }

        try? session.setMode(AVAudioSession.Mode.voiceChat)
        if err != nil {
            NSLog("Unable to change audio mode because : \(String(describing: err?.localizedDescription))")
            err = nil
        }
        let sampleRate: Double = 44100.0
        try? session.setPreferredSampleRate(sampleRate)
        if err != nil {
            NSLog("Unable to change preferred sample rate because : \(String(describing: err?.localizedDescription))")
            err = nil
        }
        try? session.setPreferredIOBufferDuration(0.005)
        if err != nil {
            NSLog("Unable to change preferred sample rate because : \(String(describing: err?.localizedDescription))")
            err = nil
        }

操作表上的发言人行:

let speakerOutput = UIAlertAction(title: "Speaker", style: .default, handler: {
            (alert: UIAlertAction!) -> Void in

                self.overrideSpeaker(override: true)
        })
        for description in currentRoute.outputs {
            if convertFromAVAudioSessionPort(description.portType) == convertFromAVAudioSessionPort(AVAudioSession.Port.builtInSpeaker){
                speakerOutput.setValue(true, forKey: "checked")
                break
            }
        }
        speakerOutput.setValue(UIImage(named: "ActionSpeaker.png")?.withRenderingMode(.alwaysOriginal), forKey: "image")
        optionMenu.addAction(speakerOutput)

我要在这里演讲,确实如此:

func overrideSpeaker(override : Bool) {
        do {
            let port: AVAudioSession.PortOverride = override ? .speaker : .none
            try session.overrideOutputAudioPort(port)
        } catch {
            NSLog("audioSession error toggling speaker: \(error.localizedDescription)")
        }
    }

这是我的路线更改委托,我先被覆盖,然后再获取newDeviceAvailable:

@objc func handleRouteChange(_ notification: Notification) {
guard let userInfo = notification.userInfo,
    let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
    let reason = AVAudioSession.RouteChangeReason(rawValue:reasonValue) else {
        return
}
switch reason {
case .newDeviceAvailable,
     .categoryChange:
    var audioShown = false


    for output in session.currentRoute.outputs where output.portType != AVAudioSession.Port.builtInReceiver && output.portType != AVAudioSession.Port.builtInSpeaker {
        self.showAudio()
        audioShown = true
        break
    }
    if !audioShown {
        self.showSpeaker()
    }
    break
case .routeConfigurationChange:
    break
case .override:
    break
default: ()
}

}

1 个答案:

答案 0 :(得分:0)

尽管这不是最佳答案,但您可以在调用覆盖OutputAudioPort()之前尝试调用setCategory(),并且在这样做时,请忽略.allowBluetooth选项。然后,如果他们取消选中扬声器,则必须将其放回原处。

使用AVAudioSession.currentRoute.availableInputs中的元数据,您可以将此逻辑的使用限制为仅在用户连接了airpods时使用。