"Observe audio session notifications to ensure that your app responds appropriately to route changes."
앱이 변경사항 라우트에 적합하게 응답하는 것을 보장할 수 있도록 오디오 세션 노티피케이션을 탐색합니다.
AVAudioSession
의 중요한 책임은 오디오 라우트 변경을 관리하는 것입니다. 라우트 변경은 시스템이 오디오 입력 혹은 출력을 추가하거나 제거할 때 발생합니다. 라우트 변경은 여러 가지 이유에 의해 발생하며, 사용자가 헤드폰을 꽂거나 블루투스 LE 헤드셋을 연결, USB 오디오 인터페이스를 빼는 것을 포함합니다. 이와 같은 변경사항이 발생하면 오디오 세션은 그에 맞게 오디오 시그널을 다시 라우팅하고, 모든 등록된 옵저버에게 변경사항의 세부사항을 포함해서 노티피케이션을 전달합니다.
라우트 변경에 관련이 있는 중요한 동적은 사용자가 헤드폰(iOS Human Interface Guidelines에 있는 Audio를 보시기 바랍니다)을 꽂거나 제거할 때 발생합니다. 사용자가 선이 있는 혹은 무선 헤드폰을 연결하면 사용자는 오디오 재생이 계속되야 한다고 생각합니다. 사용자는 일시정지 없이 재생을 계속하기 위해 재생하고 있었던 미디어가 계속 재생되기를 기대합니다. 그러나 사용자가 헤드폰 연결을 해제하면, 사용자는 그들이 듣고 있었던 것을 자동으로 공유하길 원하지 않을 것입니다. 애플리케이션은 이와 같은 암묵적인 개인정보 요청을 존중해야 하며, 사용자가 헤드폰 연결을 해제할 때 자동으로 재생을 일시정지해야 합니다.
Audio
<>
<>
Note
AVPlayer는 앱의 오디오 세션을 모니터링하고, 라우트 변경에 적합한 방식으로 응답합니다. 사용자가 헤드폰을 연결할 때 기대한 것처럼 재생은 계속됩니다. 사용자가 헤드폰 연결을 해제하면, 재생은 자동으로 일시정지됩니다. 이와 같은 플레이어 동작을 탐색하려면 key-value으로 플레이어의 레이트 속성을 탐색함으로써 플레이어가 재생을 일시정지할 때 UI를 업데이트할 수 있습니다.
오디오 세션에 의해 포스팅된 라우트 변경 노티피케이션을 직접적으로 탐색할 수 있습니다. 이는 사용자가 헤드폰을 연결할 때 시스템이 이를 알려주는 경우에 유용하며, 그렇게 함으로써 플레이어 인터페이스에서 아이콘 혹은 메시지를 제공할 수 있습니다.
오디오 라우트 변경을 탐색하려면 routeChangeNotification
타입의 노티피케이션을 탐색하기 위한 등록부터 시작해야 합니다.
func setupNotifications() {
// Get the default notification center instance.
let nc = NotificationCenter.default
nc.addObserver(self,
selector: #selector(handleRouteChange),
name: AVAudioSession.routeChangeNotification,
object: nil)
}
@objc func handleRouteChange(notification: Notification) {
// To be implemented.
}
포스팅된 노티피케이션 객체는 라우트 변경의 세부사항을 제공하는 채워진 사용자 정보 딕셔너리를 포함합니다. 딕셔너리로부터 AVAudioSession.RouteChangeReason
값을 가져와서 이와 같은 변경에 대한 이유를 확인하시기 바랍니다. 사용자가 새 기기를 연결하면 이유는 AVAudioSession.RouteChangeReason.newDeviceAvailable
이며, 사용자가 기기를 해제하면 이유는 AVAudioSession.RouteChangeReason.oldDeviceUnavailable
입니다.
새 기기가 사용 가능해지는 경우 어느 곳에서 오디오 출력이 현재 라우트되어야 하는지를 결정하기 위해 오디오 세션에게 currentRoute
를 요청할 수 있습니다. 이 쿼리는 오디오 세션의 입력 및 출력 모든 목록을 갖고 있는 AVAudioSessionRouteDescription
객체를 반환합니다. 사용자가 기기를 해제하면 사용자 정보 딕셔너리로부터 이전 라우트에 대한 라우트 설명을 가져올 수 있습니다. 모든 경우에서 출력에 대한 라우트 설명을 쿼리할 수 있으며, 출력은 오디오 출력 라우트의 세부사항을 제공하면서 포트 설명 객체의 배열을 반환하는 것입니다.
@objc func handleRouteChange(notification: Notification) {
guard let userInfo = notification.userInfo,
let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
return
}
// Switch over the route change reason.
switch reason {
case .newDeviceAvailable: // New device found.
let session = AVAudioSession.sharedInstance()
headphonesConnected = hasHeadphones(in: session.currentRoute)
case .oldDeviceUnavailable: // Old device removed.
if let previousRoute =
userInfo[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription {
headphonesConnected = hasHeadphones(in: previousRoute)
}
default: ()
}
}
func hasHeadphones(in routeDescription: AVAudioSessionRouteDescription) -> Bool {
// Filter the outputs to only those with a port type of headphones.
return !routeDescription.outputs.filter({$0.portType == .headphones}).isEmpty
}
앱이 인터럽션에 대해 적합하게 응답하는 것을 보장하기 위해서 오디오 세션 노티피케이션을 탐색합니다.
https://developer.apple.com/documentation/avfaudio/avaudiosession/responding_to_audio_session_interruptions
https://velog.io/@panther222128/Responding-to-Audio-Session-Interruptions