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

15
我有一个视频播放器,可以在iOS命令中心和锁定屏幕中播放。当我在应用程序中切换播放/暂停按钮时,它应该通过更新nowPlayingInfoMPNowPlayingInfoCenter)来更新命令中心(MPRemoteCommandCenter)中的播放/暂停按钮。我不确定为什么它没有更新。
例如,如果我使用自定义按钮暂停视频,在应用程序中,命令中心仍然显示暂停按钮(这意味着视频仍在播放,这是错误的)。

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

有什么想法吗?

更新

虽然我找到了解决方案,但在我的情况下并不完美。所以在我的应用程序中,我有两个视图控制器。让我们称它们为FeedVCPlayerVC。因此,FeedVC具有始终播放但已静音的AVPlayer。如果您单击其中一个,则会创建PlayerVC并播放完整视频。如果我在进入PlayerVC之前暂停FeedVC中的AVPlayer,则NowPlayingInfoCenter中的“播放/暂停”按钮将完美工作!

是否有一种方法可以使这项工作正常而无需暂停FeedVC中的视频?

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


我明白了,兄弟。给我一些时间回家,我会向你展示我的解决方案。 - Brandon A
我也遇到了同样的问题...你找到解决方法了吗? - Aslam
1个回答

12

当您为nowPlayingInfo设置字典时,需要适当设置MPNowPlayingInfoPropertyPlaybackRate的值。 MPNowPlayingInfoCenter期望使用NSNumber包装的Double类型值,其中1.0表示正在播放,0.0表示未播放。以下是我在项目中设置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下载我的应用程序查看此操作。
编辑(针对评论的答复)
“有没有办法使其无需暂停FeedVC中的视频就能正常工作。”
没有看到你的代码,很难给你一个确定的答案。不过,在启动PlayerVC的媒体之前暂停任何正在进行的媒体是有意义的。
“经过一段时间,播放时间仍在继续计数。”
经过一定时间后,根据NowPlayingInfoCenter中的NSTimer属性,经过时间会逐渐减少。只有当计时器的值达到您在MPMediaItemPropertyPlaybackDuration中设置的值时,或者您更新了MPNowPlayingInfoPropertyElapsedPlaybackTime时,计时器才会停止。
我的建议是编写一个“清除”NowPlayingInfoCenter的方法。该方法应将所有关键值分别设置为0.0或nil。在每次从PlayerVC播放媒体之前调用此“清除”方法。然后,一旦从PlayerVC播放,就像我在答案中粘贴的方法一样设置NowPlayingInfoCenter键值以设置新播放媒体的新值。

1
我的代码不是已经用nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.ratenowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = player.rate自动完成了这个任务吗? - JEL
另外,我从苹果的示例代码中获取:https://developer.apple.com/library/content/samplecode/MPRemoteCommandSample/Introduction/Intro.html#//apple_ref/doc/uid/TP40017322 - JEL
我今晚稍后会更新我的答案。我在工作中,身边没有我的个人电脑。但是我在一个个人项目中已经做过这个,而且它运行得很好。我认为它应该像上面那样,但我今晚会更新这个。 - Brandon A
好的,谢谢!请您也看一下我的“更新”部分,因为我提到了elapsed time似乎不能正常工作。 - JEL
@JEL 我更新了我的答案。如果这对你有帮助,请告诉我。如果不行,我们可以聊天,我可以为你解决问题。 - Brandon A
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接