【问题标题】:Play/Pause and Elapsed Time not updating in iOS command center properly播放/暂停和已用时间未在 iOS 命令中心正确更新
【发布时间】:2017-09-03 02:12:45
【问题描述】:

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

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

这就是我更新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 并播放完整视频。 如果我在转到PlayerVC 之前暂停FeedVC 中的AVPlayer,那么NowPlayingInfoCenter 中的“播放/暂停”按钮将完美运行!

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

另一个问题是,如果我不暂停 FeedVC 中的玩家,elapsed time 会继续计数。如果有多个玩家在玩,播放/暂停按钮和经过的时间似乎不正确。

【问题讨论】:

  • 我得到了你,伙计,给我时间回家,我会告诉你我的解决方案。
  • 我也面临同样的问题..你找到解决方案了吗

标签: ios objective-c swift mpmediaitem mpnowplayinginfocenter


【解决方案1】:

当您为nowPlayingInfo 设置字典时,您需要适当地设置MPNowPlayingInfoPropertyPlaybackRate 值。 MPNowPlayingInfoCenter 期望 1.0(正在播放)或 0.0(未播放)值作为包裹在 NSNumber 对象中的 Double。您将在下面找到我如何在项目中设置 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:) 来更新设备的控制台。

我将currentTime (Double) 作为我的播放器的属性进行跟踪。如果传入了currentTime,这意味着我们要玩,所以将MPNowPlayingInfoPropertyPlaybackRate设置为1.0并将MPNowPlayingInfoPropertyElapsedPlaybackTime设置为currentTime。这将设置当前时间以在设备的控制台中开始自动播放。

同样,如果没有currentTime 传递,那么我们已经停止或暂停。在这种情况下,我们将MPNowPlayingInfoPropertyPlaybackRate 设置为0.0,并且不包括MPNowPlayingInfoPropertyElapsedPlaybackTime

Download我的应用程序以查看此操作。


编辑(对 cme​​ts 的回答)

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

没有看到你的代码很难给你一个明确的答案。不过,在开始 PlayerVC 的媒体之前暂停任何正在进行的媒体是有意义的。


“经过的时间不断计算”

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

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

【讨论】:

  • 我的代码不会自动使用nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.ratenowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = player.rate 执行此操作吗?
  • 另外,我是从 Apple 的示例代码中得到的:developer.apple.com/library/content/samplecode/…
  • 今晚晚些时候我会更新我的答案。我在工作,没有我的个人电脑。但我在一个个人项目中做到了这一点,效果很好。我以为它就像上面一样,但我今晚会更新。
  • 好的,谢谢!还请查看我的“更新”,因为我还提到 elapsed time 似乎无法正常工作。
  • @JEL 我更新了我的答案。如果这对您有帮助,请告诉我。如果没有,我们可以进行聊天,我可以指导您完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-06
  • 1970-01-01
  • 2012-07-29
  • 1970-01-01
  • 2016-08-13
  • 2017-12-11
  • 1970-01-01
相关资源
最近更新 更多