Я настраиваю свое приложение iOS для воспроизведения файлов .mp3 и разрешаю управление из командного центра. Тем не менее, я столкнулся с очень странной проблемой с моим AVAudioPlayer. Я установил обработчик для события переключения воспроизведения / паузы, но когда я приостанавливаю проигрыватель, кажется, что он продолжает «играть» в фоновом режиме. Если я подожду несколько секунд, а затем нажму кнопку воспроизведения, он будет перемещаться вперед по дорожке, как если бы он молча воспроизводился во время паузы.
Кроме того, я настроил функцию поиска, которая устанавливает currentTime игрок, но когда я нажимаю паузу, он возвращается к тому месту, где он был изначально в файле.
Я полностью теряюсь в том, почему это происходит в любом случае. Единственное, что я подозреваю, это то, что я неправильно настраиваю ни свой плеер, ни пульты управления транспортом.
Я настроил свой проект так, чтобы одноэлементный SoundManager обрабатывал аудиофайлы, которые в данный момент находятся в очереди, и предоставляет функции для управления аудио. Когда вызывается playTrack, он устанавливает новый экземпляр AVAudioPlayer с файлом в заданной позиции, а затем начинает воспроизведение.
Код ниже (без удаления ненужных методов):
import Foundation
import AVFoundation
import MediaPlayer
open class SoundManager {
private var session = AVAudioSession.sharedInstance()
private var player: AVAudioPlayer?
private var trackList: [String]
private var currentPosition: Int
static let shared = SoundManager()
private init() {
try? session.setCategory(.playback)
trackList = [String]()
currentPosition = 0
setupRemoteTransportControls() // This method hooks into the MPRemoteCommandCenter and adds targets
}
func setupRemoteTransportControls() {
// Get the shared MPRemoteCommandCenter
let commandCenter = MPRemoteCommandCenter.shared()
// Add handler for Play Command
commandCenter.playCommand.addTarget { [unowned self] event in
if let player = self.player {
if !player.isPlaying {
self.player?.play()
return .success
}
return .commandFailed
}
else{
return .commandFailed
}
}
// Add handler for Pause Command
commandCenter.togglePlayPauseCommand.addTarget { [unowned self] event in
if let player = self.player {
if player.isPlaying {
self.player?.pause()
return .success
}
return .commandFailed
}
else {
return .commandFailed
}
}
// Seek
commandCenter.changePlaybackPositionCommand.addTarget{ [unowned self] event in
if let changePlaybackPositionCommandEvent = event as? MPChangePlaybackPositionCommandEvent {
let time = changePlaybackPositionCommandEvent.positionTime
self.seek(to: time)
return .success
}
return .commandFailed
}
}
func playTrack(atPosition: Int = 0){
self.player?.delegate = nil
self.player?.stop()
let fileName = trackList[atPosition]
let path = Bundle.main.path(forResource: fileName, ofType: "mp3")!
let url = URL(fileURLWithPath: path)
try? session.setActive(true)
self.player = try? AVAudioPlayer(contentsOf: url)
self.player?.prepareToPlay()
self.player?.play()
refreshNowPlaying()
}
func refreshNowPlaying() {
// Code removed, this just updates metadata on the lock screen
}
func addToTrackList(files: [String]) {
trackList.append(contentsOf: files)
}
}