Я создаю приложение для воспроизведения аудио, которое загружает mp3-файлы с URL. Я хочу получить функциональность iOS блокировки экрана и реализовал MPNowPlayingInfoCenter и MPRemoteCommandCenter, как вы увидите ниже. По какой-то причине временная позиция и продолжительность не будут обновляться, пока я не нажму одну из кнопок ПОСЛЕ воспроизведения звука (завершена буферизация). Как я могу получить время для автоматического обновления, как только будет воспроизводиться mp3?
func playNewProgram() {
let currentUrl: URL? = (player.currentItem?.asset as? AVURLAsset)?.url
guard program?.playLink != currentUrl else {
return
}
guard let url = program?.playLink else {
return
}
let item = AVPlayerItem(url: url)
self.player.replaceCurrentItem(with: item)
audioPos = 0
playAudio()
}
func resetPlayer() {
guard let url = program?.playLink else {
return
}
let item = AVPlayerItem(url: url)
self.player.replaceCurrentItem(with: item)
audioPos = 0
player.pause()
playerPaused = true
}
func togglePlayPause() {
pausePlayer(!playerPaused)
}
func pausePlayer(_ pause: Bool) {
playerPaused = pause
if playerPaused {
player.pause()
}
else {
// This allows the audio to be played while the phone is on silent
playAudio()
}
}
func playAudio() {
playerPaused = false
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
} catch(let error) {
print(error.localizedDescription)
}
player.play()
updateLockScreen(with: self.program)
}
func sliderEditingChanged(editingStarted: Bool) {
if editingStarted {
// Set a flag stating that we're seeking so the slider doesn't get updated by the periodic time observer on the player
seeking = true
pausePlayer(true)
}
// Do the seek if we're finished
if !editingStarted {
let targetTime = CMTime(seconds: audioPos * audioDuration,
preferredTimescale: 600)
player.seek(to: targetTime) { _ in
// Now the seek is finished, resume normal operation
self.seeking = false
self.pausePlayer(false)
}
}
}
func goForward30() {
if let currentTime = player.currentItem?.currentTime(), let duration = player.currentItem?.duration {
var newTime = CMTimeGetSeconds(currentTime) + 30
if newTime >= CMTimeGetSeconds(duration) {
newTime = CMTimeGetSeconds(duration)
}
player.seek(to: CMTime(value: CMTimeValue(newTime * 600), timescale: 600)) { _ in
self.updateLockScreen(with: self.program)
}
if !playerPaused {
player.pause()
playAudio()
}
}
}
func goBackward15() {
if let currentTime = player.currentItem?.currentTime() {
var newTime = CMTimeGetSeconds(currentTime) - 15
if newTime <= 0 {
newTime = 0
}
player.seek(to: CMTime(value: CMTimeValue(newTime * 600), timescale: 600)) { _ in
self.updateLockScreen(with: self.program)
}
if !playerPaused {
player.pause()
playAudio()
}
}
}
// MARK: - MPMediaPlayer
func setupRemoteCommandCenter() {
let commandCenter = MPRemoteCommandCenter.shared()
// MARK: Play
commandCenter.playCommand.addTarget { event in
self.togglePlayPause()
return .success
}
// MARK: Pause
commandCenter.pauseCommand.addTarget { event in
self.togglePlayPause()
return .success
}
// MARK: Skip
func skipBackward(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
guard let command = event.command as? MPSkipIntervalCommand else {
return .noSuchContent
}
goBackward15()
return .success
}
let skipBackwardCommand = commandCenter.skipBackwardCommand
skipBackwardCommand.isEnabled = true
skipBackwardCommand.addTarget(handler: skipBackward)
skipBackwardCommand.preferredIntervals = [-15]
func skipForward(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
guard let command = event.command as? MPSkipIntervalCommand else {
return .noSuchContent
}
goForward30()
return .success
}
let skipForwardCommand = commandCenter.skipForwardCommand
skipForwardCommand.isEnabled = true
skipForwardCommand.addTarget(handler: skipForward)
skipForwardCommand.preferredIntervals = [30]
}
func updateLockScreen(with program: ProgramData?) {
// Define Now Playing Info
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
if let artist = program?.series {
nowPlayingInfo[MPMediaItemPropertyArtist] = artist
}
if let title = program?.title {
nowPlayingInfo[MPMediaItemPropertyTitle] = title
}
// Shows LIVE label instead of slider
// nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = true
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = audioDuration
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = audioPos * audioDuration
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}