Выключить воспроизведение звука? - PullRequest
1 голос
/ 07 марта 2019

Я использую AVPlayer для воспроизведения звука с URL.Все работает нормально, но я не знаю, как остановить воспроизведение текущего аудио, когда я нахожусь в другом ViewController Я не хочу звонить player.pause() в viewWillDisappear(), потому что я хочу остановить его в определенных случаях, ноЯ хочу по-прежнему воспроизводить звук в фоновом режиме, когда приложение неактивно.

Я включил его в настройках приложения XCode для фонового воспроизведения, когда приложение неактивно enter image description here

2-й вопрос: могу ли я улучшить этот класс или все в порядке?

protocol AVPlayerServiceDelegate {
    func playerDidUpdateCurrentPlayingTime(_ time: CMTime)

}

class AVPlayerService {
    static let instance = AVPlayerService()

    private var audioPlayer: AVPlayer!
    public weak var delegate: AVPlayerServiceDelegate?

    func setupPlayer(forURL url: URL) {
        let playerItem: AVPlayerItem = AVPlayerItem(url: url)
        audioPlayer = AVPlayer(playerItem: playerItem)
        audioPlayer.play()

        audioPlayer.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main) { (CMTime) -> Void in
            if self.audioPlayer.currentItem?.status == .readyToPlay {
                self.delegate?.playerDidUpdateCurrentPlayingTime(self.audioPlayer.currentTime())
            }
        }
    }

    var isPlaying: Bool {
        return audioPlayer.isPlaying
    }

    var isPaused: Bool {
        return audioPlayer.isPaused
    }

    var rate: Float {
        return audioPlayer.rate
    }

    func seek(to time: CMTime) {
        audioPlayer.seek(to: time)
    }

    func seekToBeginning() {
        audioPlayer.seek(to: CMTimeMake(value: 0, timescale: 1))
    }

    func replay() {
        audioPlayer.seek(to: CMTimeMake(value: 0, timescale: 1))
        audioPlayer.play()
    }

    func pause() {
        if let audioPlayer = audioPlayer {
            audioPlayer.pause()
        }
    }

    func play() {
        audioPlayer.play()
    }

    func freshInstance() {
        audioPlayer = AVPlayer()
    }

    var assetDuration: CMTime {
        get {
            return audioPlayer.currentItem!.asset.duration
        }
    }
    }

1 Ответ

2 голосов
/ 07 марта 2019

Вам необходим механизм для общения с player объектом, чтобы выполнить над ним действия.
Есть много способов сделать это.

Лично я бы создал специальный класс для игрока, который занимается его созданием, загрузкой аудио-ресурса, воспроизведением, приостановкой и т. Д.
Тогда я хотел бы, чтобы этот класс был одноэлементным, чтобы я мог получить к нему доступ из любого места, или внедрить его и передать его другим классам, где он будет использоваться.

Базовый пример:

class MyAudioPlayer {
    static let shared = MyAudioPlayer()

    private var player: AVAudioPlayer?

    func load(_ url: URL) {
        player = try? AVAudioPlayer(contentsOf: url)
    }

    func play(url: URL) {
        load(url: url)
        player?.play()
    }

    func pause() {
        player?.pause()
    }

    func stop() {
        player?.stop()
    }     
}

Отправка действий из любого места в приложении:

MyAudioPlayer.shared.play(someURL)
MyAudioPlayer.shared.pause()

Что касается воспроизведения в фоновом режиме, даже если приложение не активно, потребуется (возможно, в AppDelegate)

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, 
                                                 with: .duckOthers)
try? AVAudioSession.sharedInstance().setActive(true)
UIApplication.shared.beginReceivingRemoteControlEvents()
...