잠금화면 플레이어 재생시간 동기화

This commit is contained in:
Yu Sung 2024-12-18 22:02:41 +09:00
parent c77d186ceb
commit f909de3bfc
2 changed files with 272 additions and 239 deletions

View File

@ -1,28 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>FirebaseAppDelegateProxyEnabled</key> <key>FirebaseAppDelegateProxyEnabled</key>
<false/> <false/>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-1299501215847962~3447556960</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true/>
</dict> </dict>
<key>UIAppFonts</key>
<array>
<string>gmarket_sans_bold.otf</string>
<string>gmarket_sans_medium.otf</string>
<string>gmarket_sans_light.otf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-1299501215847962~3447556960</string>
<key>SKAdNetworkItems</key> <key>SKAdNetworkItems</key>
<array> <array>
<dict> <dict>
@ -222,5 +210,17 @@
<string>3qcr597p9d.skadnetwork</string> <string>3qcr597p9d.skadnetwork</string>
</dict> </dict>
</array> </array>
</dict> <key>UIAppFonts</key>
<array>
<string>gmarket_sans_bold.otf</string>
<string>gmarket_sans_medium.otf</string>
<string>gmarket_sans_light.otf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
</dict>
</plist> </plist>

View File

@ -46,11 +46,21 @@ final class ContentPlayerPlayManager: NSObject, ObservableObject {
override init() { override init() {
self.player = AVPlayer() self.player = AVPlayer()
do {
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.playback, mode: .moviePlayback)
try audioSession.setActive(true)
} catch {
DEBUG_LOG("Audio Session 설정 실패: \(error.localizedDescription)")
}
super.init() super.init()
} }
func setPlaylist(playlist: [AudioContentPlaylistContent]) { func setPlaylist(playlist: [AudioContentPlaylistContent]) {
resetPlayer() resetPlayer()
self.registerRemoteControlEvents()
self.playlist = playlist self.playlist = playlist
playlistManager = AudioContentPlaylistManager(playlist: playlist) playlistManager = AudioContentPlaylistManager(playlist: playlist)
playNextContent() playNextContent()
@ -70,7 +80,6 @@ final class ContentPlayerPlayManager: NSObject, ObservableObject {
.sink { [weak self] currentTime in .sink { [weak self] currentTime in
if !(self?.isEditing ?? false) { if !(self?.isEditing ?? false) {
self?.currentTime = CMTimeGetSeconds(currentTime) self?.currentTime = CMTimeGetSeconds(currentTime)
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = self?.currentTime
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
@ -110,16 +119,7 @@ final class ContentPlayerPlayManager: NSObject, ObservableObject {
} }
.store(in: &cancellables) .store(in: &cancellables)
do {
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.playback, mode: .moviePlayback)
try audioSession.setActive(true)
self.fetchAlbumArtAndUpdateNowPlayingInfo() self.fetchAlbumArtAndUpdateNowPlayingInfo()
self.registerRemoteControlEvents()
} catch {
DEBUG_LOG("Audio Session 설정 실패: \(error.localizedDescription)")
}
} }
private func checkPlaybackStart(bufferedTime: Double, isLikelyToKeepUp: Bool) { private func checkPlaybackStart(bufferedTime: Double, isLikelyToKeepUp: Bool) {
@ -138,6 +138,7 @@ final class ContentPlayerPlayManager: NSObject, ObservableObject {
DEBUG_LOG("재생 중단: 버퍼링 부족 (\(bufferedTime)초)") DEBUG_LOG("재생 중단: 버퍼링 부족 (\(bufferedTime)초)")
} }
} }
updateNowPlayingInfo()
} }
private func handlePlaybackEnded() { private func handlePlaybackEnded() {
@ -283,10 +284,24 @@ final class ContentPlayerPlayManager: NSObject, ObservableObject {
} }
} }
private func registerNowPlayingInfoCenter(with albumArtImage: UIImage?) { private func updateNowPlayingInfo() {
let center = MPNowPlayingInfoCenter.default() guard var nowPlayingInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo else { return }
var nowPlayingInfo = [String: Any]()
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player?.currentTime().seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = isPlaying ? 1.0 : 0.0
let duration = CMTimeGetSeconds(player?.currentItem?.duration ?? CMTime.zero)
if duration.isFinite {
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = duration
}
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
private func registerNowPlayingInfoCenter(with albumArtImage: UIImage?) {
guard let currentItem = player?.currentItem else { return }
var nowPlayingInfo = [String: Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = title nowPlayingInfo[MPMediaItemPropertyTitle] = title
nowPlayingInfo[MPMediaItemPropertyArtist] = nickname nowPlayingInfo[MPMediaItemPropertyArtist] = nickname
@ -296,33 +311,51 @@ final class ContentPlayerPlayManager: NSObject, ObservableObject {
} }
if let player = player { if let player = player {
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = player.currentItem?.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player.currentTime().seconds
// CMTimeGetSeconds duration
let duration = CMTimeGetSeconds(currentItem.duration)
if duration.isFinite {
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = duration
}
} }
center.nowPlayingInfo = nowPlayingInfo MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
} }
private func registerRemoteControlEvents() { private func registerRemoteControlEvents() {
let center = MPRemoteCommandCenter.shared() let center = MPRemoteCommandCenter.shared()
center.playCommand.isEnabled = true
center.playCommand.addTarget { [unowned self] (commandEvent) -> MPRemoteCommandHandlerStatus in center.playCommand.addTarget { [unowned self] (commandEvent) -> MPRemoteCommandHandlerStatus in
self.playOrPause() self.playOrPause()
return .success return .success
} }
center.pauseCommand.isEnabled = true
center.pauseCommand.addTarget { [unowned self] (commandEvent) -> MPRemoteCommandHandlerStatus in center.pauseCommand.addTarget { [unowned self] (commandEvent) -> MPRemoteCommandHandlerStatus in
self.playOrPause() self.playOrPause()
return .success return .success
} }
center.nextTrackCommand.isEnabled = true
center.nextTrackCommand.addTarget { [unowned self] (commandEvent) -> MPRemoteCommandHandlerStatus in
self.playNextContent()
return .success
}
center.previousTrackCommand.isEnabled = true
center.previousTrackCommand.addTarget { [unowned self] (commandEvent) -> MPRemoteCommandHandlerStatus in
self.playPreviousContent()
return .success
}
} }
private func unRegisterRemoteControlEvents() { private func unRegisterRemoteControlEvents() {
let center = MPRemoteCommandCenter.shared() let center = MPRemoteCommandCenter.shared()
center.playCommand.removeTarget(nil) center.playCommand.removeTarget(nil)
center.pauseCommand.removeTarget(nil) center.pauseCommand.removeTarget(nil)
center.nextTrackCommand.removeTarget(nil)
center.previousTrackCommand.removeTarget(nil)
UIApplication.shared.endReceivingRemoteControlEvents() UIApplication.shared.endReceivingRemoteControlEvents()
} }
} }