14

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

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

在此处输入图像描述

这就是我更新的方式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 个视图控制器。让我们称它们为FeedVCand PlayerVCFeedVC一直AVPlayer在播放但静音的 's 也是如此。如果您单击其中一个,PlayerVC则会创建并播放完整视频。如果我在进入之前暂停AVPlayer's,那么 NowPlayingInfoCenter 中的“播放/暂停”按钮可以完美运行!FeedVCPlayerVC

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

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

4

1 回答 1

12

当您为您设置字典时,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:)以更新设备的控制台。

我将currentTime( Double) 记录为我的播放器的属性。如果有一个currentTimepass in 这意味着我们是要玩的,所以设置MPNowPlayingInfoPropertyPlaybackRateto1.0和设置MPNowPlayingInfoPropertyElapsedPlaybackTimeto currentTime。这将设置当前时间以在设备的控制台中开始自动播放。

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

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


编辑(回答评论)

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

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


“经过的时间不断计数”

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

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

于 2017-04-10T23:32:10.133 回答