AVRoutePicker выводит звук не на устройство Airplay, а на динамик телефона и наушники

#ios #swift #airplay

Вопрос:

Я создал простой аудиоплеер в swift 5, который реализует представление AVRoutePicker. Выбор маршрута отображается без проблем, и я могу переключаться между наушниками, динамиками телефона и динамиками телефонных звонков.

Проблема, с которой я сталкиваюсь, заключается в том, что, как только я выбираю динамик Airplay, звук из моего приложения не воспроизводится через выбранный динамик Airplay, а вместо этого воспроизводится из динамика телефона, даже несмотря на то, что в указателе маршрута есть галочка рядом с устройством AirPlay.

Я могу успешно подключиться к динамику AirPlay и воспроизводить аудио через YouTube или spotify, поэтому я знаю, что это должно быть возможно.

Я надеюсь, что я допустил простую ошибку в своем коде — я не получаю никаких ошибок, поэтому его немного сложно отлаживать.

Мой код:

 import UIKit
import AVFoundation //audio-video foundation
import AVKit

let rect = CGRect(x: 10, y: 10, width: 100, height: 100)
let myView = UIView(frame: rect)

class ViewController: UIViewController, AVAudioRecorderDelegate, UITableViewDelegate, UITableViewDataSource {
    
    var recordingSession: AVAudioSession!
    var audioRecorder: AVAudioRecorder!
    var audioPlayer: AVAudioPlayer!
    var numberOfRecords = 0

@IBOutlet weak var TestButton1: UIButton!
@IBOutlet weak var MyTableView: UITableView!
@IBOutlet weak var buttonLabel: UIButton!
@IBAction func record(_ sender: Any)

{
    //Check if we have an active recorder
    
    if audioRecorder == nil
    
    {
        numberOfRecords  = 1
        let filename = getDirectory().appendingPathComponent("(numberOfRecords).m4a")
        
        let settings = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 12000, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue]
        
        //Start rec
        
        do
        {
            audioRecorder = try AVAudioRecorder(url: filename, settings: settings)
            audioRecorder.delegate = self
            audioRecorder.record()
            
            
            
            buttonLabel.setTitle("Stop Recording", for: .normal)
        }
        catch
        {
            displayAlert(title:"Ups!", message: "Recording failed")
        }
        
    }
    else
    {
        //stopping rec
        audioRecorder.stop()
        audioRecorder = nil
        
        UserDefaults.standard.set(numberOfRecords, forKey: "myNumber")
        MyTableView.reloadData()
        
        buttonLabel.setTitle("Start Recording", for: .normal)
        
    }
    
}




@IBAction func RoutePicker(_ sender: Any) {
    let routePickerView = AVRoutePickerView()

    self.view.addSubview(routePickerView)
    if let routePickerButton = routePickerView.subviews.first(where: { $0 is UIButton }) as? UIButton {
    
    routePickerButton.sendActions(for: .touchUpInside)
    }
}


override func viewDidLoad() {
    super.viewDidLoad()
    
    let routePickerView = AVRoutePickerView()
    
    self.view.addSubview(routePickerView)
  
    if let routePickerButton = routePickerView.subviews.first(where: { $0 is UIButton }) as? UIButton {
    
    routePickerButton.sendActions(for: .touchUpInside)

    }
    
    //Setting up session
    recordingSession = AVAudioSession.sharedInstance()
    
    if let number:Int = UserDefaults.standard.object(forKey: "muNumber") as? Int
    {
        numberOfRecords = number
    }
    
    if (recordingSession.responds(to: #selector(AVAudioSession.requestRecordPermission(_:)))) {
        AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
            if granted {
            
                
                print("granted")
                
                do {
                    try self.recordingSession.setCategory(AVAudioSession.Category.playAndRecord)
                    try self.recordingSession.setActive(true)
                }
                catch {
                    
                    print("Couldn't set Audio session category")
                }
            } else{
                print("not granted")
            }
        })
    }

}

 //Function that gets path to directory
 func getDirectory() -> URL
    {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentDirectory = paths[0]
        return documentDirectory
    }

    //Function that displays an alert
    func displayAlert(title:String, message:String)
    {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "dismiss", style: .default, handler: nil))
        present(alert, animated: true, completion: nil)
        
    }
    
    //SETTING UP TABLE VIEW//
    
    func tableView (_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return numberOfRecords
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = String(indexPath.row   1)
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        
        let path = getDirectory().appendingPathComponent("(indexPath.row   1).m4a")
        
        do
        {
           // try recordingSession.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
            
            audioPlayer = try AVAudioPlayer(contentsOf: path)

            audioPlayer.play()
        }
        catch
        {
        }
        
    }

}
 

Я думаю, что линия try recordingSession.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker) здесь ключевая, так как, когда это не указано, мы не можем переключаться между динамиком телефона или наушниками.
Мне интересно, есть ли эквивалент для динамиков Airplay.

Xcode 12.5 Устройство IOS: 13.1.2 macOS: Big Sur 11.0.1 Swift: 4

Комментарии:

1. Кто-нибудь знает, правильны ли настройки здесь: т. е. поддерживает ли airplay файлы .m4a? #