MPRemoteCommandCenter кнопка паузы / воспроизведения создать более общий экземпляр AVAudioPlayer? - PullRequest
0 голосов
/ 23 октября 2019

Мое приложение представляет собой музыкальный проигрыватель, использующий AVAudioPlayer с одноцветным рисунком и фоновым режимом. Все идет хорошо, но после добавления командного центра для управления заблокированным экраном я обнаружил одно странное поведение.

Когда я использую кнопку паузы / воспроизведения на заблокированном экране, иногда это может создать дополнительный sharedInstance ofaudioPlay на фоне , потому что я нашел многократную дублирующую печать, например, в моем коде commandCenter.pauseCommand. Аудио приостанавливается или возобновляет воспроизведение, но следующий щелчок по кнопке командного центра и по кнопке воспроизведения / паузы в ВК приложения не имеет никакого эффекта. Это многопоточная проблема, ну, я очень новичок в Swift, любая помощь или подсказка о том, как найти / решить эту проблему, приветствуется.

Обновление , один сценарий для повторения:

  1. Приостановка воспроизведения звука в приложении.
  2. Заблокируйте экран с помощью кнопки питания, затем снова откройте экран и нажмите кнопку воспроизведения на панели управления.
  3. Возобновление звукаДля воспроизведения на заблокированном экране и по истечении указанного времени продолжите обработку, затем снова откройте приложение, панель процессов по-прежнему останавливается на предыдущей позиции, и в следующий раз щелчок воспроизведения / паузы не действует.

/ / / кодкомандного центра и MPMediaItemProperty

func setUpLockedScreenControl() {
        // add control panel on locked screen
        let commandCenter = MPRemoteCommandCenter.shared()
        commandCenter.pauseCommand.isEnabled = true
        commandCenter.playCommand.isEnabled = true
        commandCenter.nextTrackCommand.isEnabled = true
        commandCenter.previousTrackCommand.isEnabled = true

        commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            SongData.isPlaying = false
            AudioManager.sharedInstance.pauseMusic()

            self.updateLockedScreenPlayingInfo()
            print("pause music in command center")
            self.playOrPauseButton.setImage(UIImage(named: "Play"), for: .normal)
            self.playOrPauseButton.imageView?.contentMode = .scaleAspectFit

            return .success
        }

        commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            SongData.isPlaying = true
            AudioManager.sharedInstance.playMusic()

            self.updateLockedScreenPlayingInfo()
            print("play music in command center")
            // add to continue update playing progress
            self.playOrPauseButton.setImage(UIImage(named: "Pause"), for: .normal)
            self.playOrPauseButton.imageView?.contentMode = .scaleAspectFit
            return .success
        }

        commandCenter.nextTrackCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            self.goNextSong()
            self.updateLockedScreenPlayingInfo()
            return .success
        }

        commandCenter.previousTrackCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            self.goPreviousSong()
            self.updateLockedScreenPlayingInfo()
            return .success
        }
    }

    func updateLockedScreenPlayingInfo() {

        var info  = Dictionary<String, Any>()
        info[MPMediaItemPropertyTitle] = SongData.songList[SongData.currentTrack].songName
        info[MPMediaItemPropertyAlbumTitle] = SongData.songList[SongData.currentTrack].albumName
        info[MPMediaItemPropertyArtist] = SongData.songList[SongData.currentTrack].artistName

        let image = SongData.songList[SongData.currentTrack].albumArtwork
        let artwork = MPMediaItemArtwork.init(boundsSize: image.size, requestHandler: { (size) -> UIImage in
                return image
        })

        info[MPMediaItemPropertyArtwork] = artwork
        info[MPMediaItemPropertyPlaybackDuration] = AudioManager.sharedInstance.audioPlayer.duration

        if SongData.isPlaying == true {
            let time = AudioManager.sharedInstance.audioPlayer.currentTime
            info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = time
            info[MPMediaItemPropertyPlaybackDuration] = AudioManager.sharedInstance.audioPlayer.duration
            info[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
            print("SongData.isPlaying == true, current time is:", time)
        } else {
            let time = AudioManager.sharedInstance.audioPlayer.currentTime
            info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = time
            info[MPMediaItemPropertyPlaybackDuration] = AudioManager.sharedInstance.audioPlayer.duration
            info[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
            print("SongData.isPlaying == false, current time is:", time)
        }

        MPNowPlayingInfoCenter.default().nowPlayingInfo = info
    }

/ / / здесь информация о консоли, когда произошла ошибка, в этом случае дважды печатать commandCenter.playCommand код

Playback OK
Session is Active
2019-10-23 11:38:06.331882+0800 LocalMusicPlayer[12366:853141] Can't end BackgroundTask: no background task exists with identifier 22 (0x16), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
SongData.isPlaying == true, current time is: 5.15344671201814
play music in command center
SongData.isPlaying == true, current time is: 5.155759637188209
play music in command center

/ / / backgroundрежим установлен в appDelegate, а Can't end BackgroundTask происходит только на iOS 13, я думаю, это может быть проблемой на стороне Apple.

func applicationWillResignActive(_ application: UIApplication) {

    do {
        // set options as empty [] could show control panel in locked screen.
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
        print("Playback OK")
        try AVAudioSession.sharedInstance().setActive(true)
        print("Session is Active")
     } catch {
        print(error)
     }
}

/ / / Audio Manager.swift для управления audioPlayer

class AudioManager: NSObject, AVAudioPlayerDelegate {
    // use Singleton pattern keep the music continuing when user move through the App.
    static let sharedInstance = AudioManager()

    var audioPlayer: AVAudioPlayer!
    var playingSong: SongData?

    private override init() {
        super.init()  
    }
... ... 
}

/ / / Воспроизведение / Пауза в приложенияхВК

@IBAction func PlayOrPauseMusic(_ sender: UIButton) {
        if SongData.isPlaying {
            print("pause the music playing")
            SongData.isPlaying = false
            AudioManager.sharedInstance.pauseMusic()

            updateLockedScreenPlayingInfo()
            playOrPauseButton.setImage(UIImage(named: "Play"), for: .normal)
            playOrPauseButton.imageView?.contentMode = .scaleAspectFit
        } else {
            print("continue to play current music")
            SongData.isPlaying = true
            AudioManager.sharedInstance.playMusic()

            updateLockedScreenPlayingInfo()
            playOrPauseButton.setImage(UIImage(named: "Pause"), for: .normal)
            playOrPauseButton.imageView?.contentMode = .scaleAspectFit
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...