播放/暂停和已用时间未在iOS命令中心正确更新

JEL*_*JEL 13 objective-c mpmediaitem ios mpnowplayinginfocenter swift

我有一个可以从iOS命令中心和锁定屏幕播放的视频播放器.当我在我的应用程序切换播放/暂停按钮,它应该更新指挥中心(播放/暂停按钮,MPRemoteCommandCenter通过更新)nowPlayingInfo(MPNowPlayingInfoCenter).我不确定为什么它没有更新.

例如,如果我在我的应用程序中使用自定义按钮暂停视频,则命令中心仍会显示暂停按钮(意味着视频仍在播放,这是错误的.)

在此输入图像描述

这是我更新的方式nowPlayingInfo:

func updateMPNowPlayingInforCenterMetadata() {
    guard video != nil else {
        nowPlayingInfoCenter.nowPlayingInfo = nil
        return
    }

    var nowPlayingInfo = nowPlayingInfoCenter.nowPlayingInfo ?? [String: Any]()

    let image: UIImage
    if let placeholderLocalURL = video.placeholderLocalURL, let placeholderImage = UIImage(contentsOfFile: placeholderLocalURL.path) {
        image = placeholderImage
    } else {
        image = UIImage()
    }

    let artwork = MPMediaItemArtwork(boundsSize: image.size, requestHandler: { _ -> UIImage in
        return image
    })

    nowPlayingInfo[MPMediaItemPropertyTitle] = video.title
    nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = video.creator?.name ?? " "
    nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork

    nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = Float(video.duration)
    nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = Float(currentTime) // CMTimeGetSeconds(player.currentItem!.currentTime())
    nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
    nowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = player.rate

    nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo

    if player.rate == 0.0 {
        state = .paused
    } else {
        state = .playing
    }
}
Run Code Online (Sandbox Code Playgroud)

使用KVO,当玩家rate改变时,我称之为此功能:

// MARK: - Key-Value Observing Method

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard context == &assetPlaybackManagerKVOContext else {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        return
    }

    } else if keyPath == #keyPath(AVPlayer.rate) {
        updateMPNowPlayingInforCenterMetadata()
    }
}
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

UPDATE

我找到了一个解决方案,但在我的情况下并不完美.所以在我的应用程序中我有2个视图控制器.让我们把它们FeedVCPlayerVC.因此,FeedVC具有AVPlayer的是总是打不过的静音.如果您单击其中一个,则会PlayerVC创建并播放完整视频.如果我暂停AVPlayer中的FeedVC才去PlayerVC那么'播放/暂停’,在NowPlayingInfoCenter按钮完美的作品!

有没有办法让这项工作,而不必暂停视频FeedVC

另一个问题是,elapsed time如果我不暂停球员,我会继续计算FeedVC.似乎如果正在播放多个播放器,则播放/暂停按钮和经过的时间不正确.

Bra*_*n A 7

设置字典时,nowPlayingInfo您需要MPNowPlayingInfoPropertyPlaybackRate适当地设置值.的MPNowPlayingInfoCenter期待任一1.0(播放)或0.0(未播放)值作为一个Double包装在一个NSNumber对象.您将在下面找到我nowPlayingInfo在项目中设置方式的代码.

func setNowPlayingMediaWith(song: SUSong, currentTime: Double?) {

    var playingInfo:[String: Any] = [:]

    if let title = song.title {
        playingInfo[MPMediaItemPropertyTitle] = title
    }

    if let songID = song.id {
        playingInfo[MPMediaItemPropertyPersistentID] = songID
    }
    if let artist = song.artist, let artistName = artist.name {
        playingInfo[MPMediaItemPropertyArtist] = artistName
    }

    if let album = song.album, let albumTitle = album.title {
        var artwork:MPMediaItemArtwork? = nil
        if let album = song.album, let artworkData = album.artwork {
            artwork = MPMediaItemArtwork(boundsSize: Constants.Library.Albums.thumbSize, requestHandler: { (size) -> UIImage in
                return UIImage(data: artworkData as Data)!
            })
        }
        if artwork != nil {
            playingInfo[MPMediaItemPropertyArtwork] = artwork!
        }
        playingInfo[MPMediaItemPropertyAlbumTitle] = albumTitle
    }

    var rate:Double = 0.0
    if let time = currentTime {
        playingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = time
        playingInfo[MPMediaItemPropertyPlaybackDuration] = song.duration
        rate = 1.0
    }
    playingInfo[MPNowPlayingInfoPropertyPlaybackRate] = NSNumber(value: rate)
    playingInfo[MPNowPlayingInfoPropertyMediaType] = NSNumber(value: MPNowPlayingInfoMediaType.audio.rawValue)
    MPNowPlayingInfoCenter.default().nowPlayingInfo = playingInfo
}
Run Code Online (Sandbox Code Playgroud)

在这个方法中,我传递的song是我的播放器当前已加载的内容.每当用户选择播放或暂停时,我都会呼叫setNowPlayingMediaWith(song:currentTime:)更新设备的控制台.

我跟踪currentTime(Double)作为我的播放器的属性.如果currentTime传入,则意味着我们要播放,所以设置MPNowPlayingInfoPropertyPlaybackRate1.0并设置MPNowPlayingInfoPropertyElapsedPlaybackTimecurrentTime.这将设置当前开始在设备控制台中自动播放的时间.

同样,如果没有currentTime通过,那么我们已经停止或暂停.在这种情况下,我们设置MPNowPlayingInfoPropertyPlaybackRate0.0,我们不包括MPNowPlayingInfoPropertyElapsedPlaybackTime.

下载我的应用程序以查看此操作.


编辑(回答评论)

"有没有办法让这项工作无需暂停FeedVC中的视频"

如果没有看到您的代码,很难给出明确的答案.在开始播放媒体之前暂停任何正在进行的媒体是有意义PlayerVC的.


"经过的时间不断计算"

经过的时间将根据NSTimer属性打开倒计时所用的时间NowPlayingInfoCenter.只有当计时器值达到您设置的值MPMediaItemPropertyPlaybackDuration或更新时,此计时器才会停止MPNowPlayingInfoPropertyElapsedPlaybackTime.

我的建议是写一个"清除"的方法NowPlayingInfoCenter.此方法应设置将所有键值分别设置为0.0或nil.每次播放媒​​体之前,请每次调用此"清除"方法PlayerVC.然后,一旦你玩了PlayerVC,设置NowPlayingInfoCenter键值就像我在答案中粘贴的方法一样设置新播放媒体的新值.