Audio Session은 앱, 운영체제, 그리고 오디오 하드웨어 간의 중개자 역할을 하며 오디오 환경을 정의하고 관리한다.
기본적인 설정은 다음과 같으며 목적에 따라 변경이 가능하다.
AudioSession의 객체를 통해 설정한다.
AudioSession의 라이프사이클은 앱의 라이프사이클과 일치하므로, 일반적으로 앱이 실행될 때 한번 구성한다.
application didFinishLauncingWithOptions에서 작성하면 좋다.
AudioSession의 기본 카테고리는 Solo Ambient로 설정되어 있다.
만약 음소거 스위치가 활성화 되어 있어도 실행하고 싶다면 Playback으로 설정한다.
let audioSession = AVAudioSession.sharedInstance()
try? audioSession.setCategory(.playback)
try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
재생중에 기기가 잠금화면이 뜰 수 있다.
그때 오디오를 계속 재생하고 싶다면 다음과 같이 설정한다.
1. Info.plist 파일에서 Request background modes 프로퍼티를 찾거나 없으면 생성한다.
2. Item 0을 App plays audio or streams audio/video using AirPlay로 설정한다.
오디오가 나오는 중에 통화가 발생한다면, 기본으로 서서히 Fade-out되다 멈춘다.
만약 사용자가 전화를 거절한 경우 다시 오디오를 재생하고 싶다면 다음과 같이 설정한다.
Notification을 등록한 후 해당 Notification을 이용해 처리한다.
NotificationCenter.default.addObserver(self, selector: #selector(handleAudioInterruption(notification:)), name: AVAudioSession.interruptionNotification, object: audioSession)
@objc func handleAudioInterruption(notification: Notification) {
guard let info = notification.userInfo,
let interruptionType = info[AVAudioSessionInterruptionTypeKey] as? AVAudioSession.InterruptionType,
let interruptionOptions = info[AVAudioSessionInterruptionOptionKey] as? AVAudioSession.InterruptionOptions else { return }
if interruptionType == .began {
// 인터럽션이 시작된 경우 처리 코드
}
if interruptionOptions == .shouldResume {
// 다시 재생하는 코드
}
}
재생 장치가 내장 스피커에서 이어폰으로는 자연스럽게 변경된다.
사용자가 오디오를 듣던 중에 이어폰으로 듣고자 연결하는 것이기에 오디오가 이어지는 것이 자연스럽다.
하지만 이어폰을 듣던 중에 이어폰이 제거되면 어떻게 될까?
사용자가 일부로 이어폰을 제거한 것인지, 혹은 오디오를 듣던 중에 다른 요인으로 인해 제거된 것인지 알 수 없다.
이럴 경우, 이어폰이 제거되었다면 재생을 멈추도록 설정할 수 있다.
NotificationCenter.default.addObserver(self, selector: #selector(handleAudioRouteChange(notification:)), name: AVAudioSession.routeChangeNotification, object: audioSession)
@objc func handleAudioRouteChange(notification: Notification) {
guard let info = notification.userInfo,
let reason = info[AVAudioSessionRouteChangeReasonKey] as? AVAudioSession.RouteChangeReason,
let prevRoute = info[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription else { return }
if reason == .oldDeviceUnavailable {
let prevOutput = prevRoute.outputs[0]
let portType = prevOutput.portType
if portType == .headphones {
// 재생을 멈추는 코드
}
}
}
오디오를 재생했을 때 다양한 상황들이 발생할 수 있다는 것을 알게 되었다.
잠금화면이 뜨거나, 통화 등의 인터럽트가 발생하거나 이어폰이 제거되는 등 일어날 수 있는 사건들을 생각하고 처리해야 겠다.