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

时间:2017-04-07 15:54:53

标签: ios objective-c swift mpmediaitem mpnowplayinginfocenter

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

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

enter image description here

这是我更新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
    }
}

使用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()
    }
}

有什么想法吗?

更新

我找到了一个解决方案,但在我的情况下并不完美。所以在我的应用程序中我有2个视图控制器。我们称他们为FeedVCPlayerVC。因此,FeedVCAVPlayer个始终在播放但已静音的PlayerVC。如果您点击其中一个,则会创建AVPlayer并播放完整视频。 如果我在转到FeedVC之前暂停PlayerVC中的FeedVC,那么"播放/暂停" NowPlayingInfoCenter中的按钮完美运行!

有没有办法让这项工作无需暂停elapsed time中的视频?

另一个问题是FeedVC如果我暂停"/text/text/text/" stripPrefix "/" stripSuffix "/" 中的玩家,则会继续计算。似乎如果正在播放多个播放器,则播放/暂停按钮和已用时间不正确。

1 个答案:

答案 0 :(得分: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
}

在这个方法中,我传递了我的播放器当前加载的song。每当用户选择播放或暂停时,我都会调用setNowPlayingMediaWith(song:currentTime:)来更新设备的控制台。

我会跟踪currentTimeDouble)作为播放器的属性。如果传递currentTime表示我们打算播放,那么请将MPNowPlayingInfoPropertyPlaybackRate设置为1.0并将MPNowPlayingInfoPropertyElapsedPlaybackTime设置为currentTime。这将设置当前开始在设备控制台中自动播放的时间。

同样,如果没有currentTime通过,那么我们已停止或暂停。在这种情况下,我们将MPNowPlayingInfoPropertyPlaybackRate设置为0.0,我们不会包含MPNowPlayingInfoPropertyElapsedPlaybackTime

Download我的应用可以看到这一点。

编辑(回复评论)

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

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

“经过的时间不断计算”

经过的时间将根据NSTimer上的NowPlayingInfoCenter属性倒计时。只有当计时器值达到您在MPMediaItemPropertyPlaybackDuration中设置的值或更新MPNowPlayingInfoPropertyElapsedPlaybackTime时,此计时器才会停止。

我的建议是写一个“清除”NowPlayingInfoCenter的方法。此方法应设置将所有键值分别设置为0.0或nil。在PlayerVC播放媒体之前,每次都要调用此“清除”方法。然后,一旦您从PlayerVC进行游戏,请设置NowPlayingInfoCenter键值,就像我在答案中粘贴的方法一样,为新播放媒体设置新值。