У меня проблемы с моим музыкальным приложением. Идея состоит в том, чтобы нажать кнопку и воспроизвести больше песен исполнителя, который играет в данный момент. Когда я нахожусь в приложении и нажимаю следующую песню, все работает нормально. Однако, если я позволю песне закончиться естественным образом, приложение воспроизведет случайную песню. Поэтому я добавил логику, чтобы сказать, что если оставшееся время песен равно 0, тогда воспроизведите следующую песню, используя func медиаплееров, потому что я знаю, что это работает. Это решило проблему, за исключением случаев, когда приложение находится в фоновом режиме. Я пытался сохранить приложение, если оно работает в фоновом режиме, но я думаю, что это не работает.
Каждый раз, когда я думаю, что решил что-то, проблема возвращается.
Я ожидаю, что произойдет блокировка исполнителя, закрытие приложения в фоновом режиме и после окончания песни воспроизведение другой песни исполнителя.
Что на самом деле происходит, так это то, что когда я блокирую исполнителя и закрываю приложение в фоновом режиме, песня заканчивается, и иногда она воспроизводит нужную песню. Иногда этого не будет. ОДНАКО когда воспроизводится не та песня, и я открываю приложение в резервной копии, текущая (неправильная) воспроизводимая песня завершается и начинается воспроизведение песни правильного исполнителя
для ясности, я думаю, что неразумно использовать логику, которая запускается, когда оставшееся время песни равно 0, чтобы перейти к следующей песне, но по какой-то причине мне это нужно
Я установил возможности для фоновой загрузки и воспроизведения аудио и изображения в картинке.
Я пытался опубликовать только соответствующий код по порядку.
у меня есть недвижимость
let mediaPlayer = MPMusicPlayerController.systemMusicPlayer
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
В моем ViewDidLoad
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
try? AVAudioSession.sharedInstance().setActive(true)
DispatchQueue.main.async {
self.clearSongInfo()
MediaManager.shared.getAllSongs { (songs) in
guard let theSongs = songs else {
return
}
self.mediaPlayer.nowPlayingItem = nil
self.newSongs = theSongs.filter({ (item) -> Bool in
return !MediaManager.shared.playedSongs.contains(item)
})
self.aSongIsInChamber = true
self.mediaPlayer.setQueue(with: MPMediaItemCollection(items: self.newSongs.shuffled())
)
self.mediaPlayer.shuffleMode = .off
self.mediaPlayer.repeatMode = .none
}
NotificationCenter.default.addObserver(self, selector: #selector(self.songChanged(_:)), name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange, object: self.mediaPlayer)
self.mediaPlayer.beginGeneratingPlaybackNotifications()
}
У меня есть функция, которая обновляет время воспроизведения и оставшееся время, и в этом у меня есть
if Int(self.songProgressSlider.maximumValue - self.songProgressSlider.value) < 1 {
print("song ended naturally, skipped")
mediaPlayer.prepareToPlay(completionHandler: { (error) in
DispatchQueue.main.async {
self.mediaPlayer.skipToNextItem()
}
})
}
Когда я играю музыку, у меня есть логическое значение isPlaying.
Если это так, то время бежит, и у меня есть это
let app = UIApplication.shared
var task: UIBackgroundTaskIdentifier?
task = app.beginBackgroundTask {
app.endBackgroundTask(task!)
}
У меня есть это, чтобы таймер работал в фоновом режиме, поэтому он будет воспроизводить следующую песню, когда оставшееся время равно 0.
Теперь, чтобы заблокировать исполнителя, у меня есть следующий код, который выполняется при нажатии кнопки
let artistPredicate: MPMediaPropertyPredicate = MPMediaPropertyPredicate(value: nowPlaying.artist, forProperty: MPMediaItemPropertyArtist)
let query: MPMediaQuery = MPMediaQuery.artists()
let musicPlayerController: MPMusicPlayerController = MPMusicPlayerController.systemMusicPlayer
query.addFilterPredicate(artistPredicate)
musicPlayerController.setQueue(with: query)