다른 앱 오디오 처리(v3.3.1)

3.3.0에서 3.3.1로 올릴 때 바꿔야 하는 코드는 없습니다. 공개 API는 그대로이고, 새 콜백 didDetectOtherAppAudioActive()는 기본 구현이 있어 필요할 때만 구현하면 됩니다.

1. 다른 앱이 오디오를 쓰는 동안의 동작

통화·VoIP·알람처럼 다른 앱이 오디오를 쓰면 측정이 잠시 멈춥니다(didInterrupt()). SDK는 자동으로 재개를 시도하는데, 3.3.1부터는 다른 앱이 오디오를 계속 쓰는 동안 측정을 끝내지 않고 기다립니다.

상황3.3.03.3.1
다른 앱이 오디오를 계속 써서 자동 재개 3번이 모두 막힘didFail(error: .interruptionRecoveryFailed) (통화가 17초만 넘어도 발생)측정을 끝내지 않고 30초마다 다시 확인. 오디오가 풀리면 자동으로 재개하고 didResume() 호출
재개가 막혔을 때 앱에 알림없음didDetectOtherAppAudioActive() 1번
다른 앱이 오디오를 놓았는데도 재개 실패interruptionRecoveryFailedinterruptionRecoveryFailed (같음)
재개될 때 didResume()2번 올 수 있고, 재개에 실패하면 didResume() 뒤 didInterrupt()가 다시 옴녹음이 실제로 다시 시작된 뒤 보통 1번. 드물게 2번 올 수 있으니 중복 호출에도 안전하게 처리해 주세요
interruptionRecoveryFailed 뒤 stopTracking()세션은 닫히지만 녹음이 남아, 통화가 끝나면 마이크가 다시 켜짐녹음도 멈춤

2. didDetectOtherAppAudioActive()

protocol AsleepSleepTrackingManagerDelegate {
    // ...
    func didDetectOtherAppAudioActive()   // optional (v3.3.1)
}
  • 인터럽션 뒤 자동 재개를 시도했지만 다른 앱이 아직 오디오를 쓰고 있어 재개하지 못했을 때 호출됩니다.
    • 통화·VoIP처럼 다른 앱 오디오가 재생 중인 경우
    • 알람처럼 오디오 세션 활성화가 거부된 경우
  • 같은 인터럽션 동안에는 한 번만 호출됩니다.
  • 호출 스레드가 보장되지 않습니다. UI 업데이트는 MainActor에서 해 주세요.
📘

사용자에게 알리는 것을 권장합니다

앱이 백그라운드에 있으면 iOS가 녹음 재개를 막을 수 있습니다. 멈춘 상태가 길어지면 로컬 알림 등으로 사용자에게 알려 주세요.

아래는 멈춘 상태가 5분 넘게 이어질 때만 로컬 알림을 띄우는 예시입니다. 재개되거나 측정이 끝나면 예약한 알림을 취소합니다. 알림 권한은 측정을 시작할 때 미리 요청해 두세요.

import UserNotifications

final class TrackingViewModel: AsleepSleepTrackingManagerDelegate {
    private let pausedNotificationId = "otherAppAudioActive"

    func didDetectOtherAppAudioActive() {
        let content = UNMutableNotificationContent()
        content.title = "수면 측정이 잠시 멈췄어요"
        content.body = "다른 앱이 5분째 오디오를 쓰고 있어요. 끝나면 측정이 자동으로 이어집니다."
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5 * 60, repeats: false)
        let request = UNNotificationRequest(identifier: pausedNotificationId, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
    }

    func didResume() {
        cancelPausedNotification()
    }

    func didClose(sessionId: String) {
        cancelPausedNotification()
    }

    private func cancelPausedNotification() {
        UNUserNotificationCenter.current()
            .removePendingNotificationRequests(withIdentifiers: [pausedNotificationId])
    }

    // ... 그 밖의 delegate 메서드
}

3. 그 밖의 변경

  • 크래시 수정
    • createSleepTrackingManager 전에 startTracking()·stopTracking()·resumeTracking() 등을 부르면 앱이 종료되던 것을, didFail(error: .configurationError)로 알리고 아무 동작도 하지 않도록 바꿨습니다.
    • 오디오 포맷 변환을 만들지 못할 때 앱이 종료되던 것을 수정했습니다.
  • Token 인증: 종료되지 않은 이전 세션을 init 때 정리하는 요청이 인증 없이 나가 실패하던 문제를 수정했습니다.
  • SDK 로그
    • 앱이 강제 종료되거나 측정 중 오류가 나도 로그가 유실되지 않도록 바로 저장합니다.
    • 로그 파일이 커져도(2MB 초과) 버리지 않고 업로드하고, 업로드에 실패하면 다음에 다시 보냅니다.
    • 3.2.x가 앱의 Documents 폴더에 남긴 AsleepSDK.log, AsleepSDK_send.log를 지웁니다. Documents의 다른 파일은 건드리지 않습니다.
  • Xcode 콘솔에 찍히던 SDK 디버그 출력을 정리했습니다.

Did this page help you?