Android 17부터 오디오 프레임워크는 오디오 재생, 오디오 포커스 요청, 볼륨 변경 API를 비롯한 백그라운드 오디오 상호작용에 제한을 적용하여 이러한 변경사항이 사용자가 의도적으로 시작되도록 합니다.
앱 개발자가 표시되는 활동 없이 오디오를 제어하려는 경우 앱에 사용 중 (WIU) 기능으로 시작된 포그라운드 서비스 (SHORT_SERVICE 유형이 아님)가 있는지 확인해야 합니다. 포그라운드 서비스는 MediaSessionEvent에 대한 응답으로 시작되거나 앱이 사용자에게 표시되는 동안 시작되는 경우 WIU 기능이 부여됩니다.
앱이 유효한 수명 주기에 있지 않은 동안 오디오 API를 호출하려고 하면 예외를 발생시키거나 실패 메시지를 제공하지 않고 오디오 재생 및 볼륨 변경 API가 자동으로 실패합니다. 오디오 포커스 API가 결과 코드 AUDIOFOCUS_REQUEST_FAILED로 실패합니다.
이러한 제한사항을 도입하는 목적은 의도치 않은 백그라운드 오디오 버그 환경을 줄이는 것입니다. 다음은 몇 가지 예입니다.
- 포그라운드 서비스 없이 오디오를 재생하는 앱은 고정될 수 있습니다. 결국 앱이 고정 해제되면 몇 시간 후에 예기치 않게 오디오 재생이 다시 시작됩니다.
- 포그라운드 서비스 없이 오디오를 재생하는 앱은 다양한 실행 제한에 직면하여 오디오 성능이 끊겼습니다.
- 활동 수명 주기에서 재생이 분리되어 재생 세션이 누출되거나 포커스 이벤트가 누출될 수 있으며, 사용자가 재생을 중지할 방법이 없습니다.
개발자는 앱을 테스트하고 의도한 오디오 사용 사례가 부정적인 영향을 받는 경우 동작 변경에 관한 의견을 제공하는 것이 좋습니다. 이 Android 17 앱 호환성 문제 추적기를 사용하여 문제를 신고해 주세요.
영향을 받는 백그라운드 오디오 사용 사례 식별
오디오 재생 구현을 감사하고 앱이 조건부 상황에서도 백그라운드 오디오 상호작용 기능을 제공하려고 하는지 확인합니다.
앱이 PIP 모드를 사용하는 등 사용자에게 표시되는 활동을 표시하는 동안 오디오를 재생하거나 오디오 API를 사용하려고만 하는 경우 이러한 변경사항의 영향을 받지 않습니다.
영상 통화 앱을 비롯해 앱에서 VOIP 기능을 제공하는 경우 오디오를 성공적으로 녹음하려면 재생에 도입되는 요구사항을 이미 충족해야 합니다 (일반적으로 권장되는 telecom API를 활용). 따라서 영향을 받지 않을 가능성이 높습니다.
화면이 꺼져 있거나 사용자가 활동을 완전히 닫은 상태에서 오디오 재생을 계속하려는 앱(음악 스트리밍 앱이나 팟캐스트 앱에서 가장 흔히 볼 수 있음)은 백그라운드 오디오 기능을 제공하는 것으로 간주되며 새로운 요구사항을 충족해야 합니다.
영향을 받을 수 있는 백그라운드 오디오 시나리오
앱이 열려 있는 동안 시작된 오디오 상호작용을 계속하거나 명시적인 사용자 트리거에 응답하는 모델을 따르지 않으면 앱의 기능이 자동으로 억제될 수 있습니다.
예를 들어 앱이 BOOT_COMPLETE에 응답하여 포그라운드 서비스를 시작하고 오디오와 상호작용하려고 하면 억제됩니다.
영향을 완화하기 위한 배경 오디오 권장사항
media3 Jetpack 라이브러리의
MediaSessionService구성요소를 사용하여 백그라운드 오디오 재생을 관리합니다.이렇게 하면 라이브러리가 재생 수명 주기를 관리하는 데 도움이 되므로 앱이 백그라운드 강화의 영향을 받지 않을 수 있습니다.
media3 라이브러리를 활용하지 않는 경우
mediaPlaybackFGS를 수동으로 시작해야 합니다. 백그라운드 오디오가 발생할 수 있는 경우 앱이 포그라운드에 있는 동안 항상 포그라운드 서비스를 시작하세요.예를 들어 앱이 일반적으로 포그라운드 전용이지만 화면이 꺼져 있는 동안 재생을 계속하는 사용자 어포던스를 포함하는 동영상 스트리밍 앱인 경우, 사용자가 시작한 재생 트리거가 발생하면 앱은 여전히 포그라운드 서비스를 시작해야 합니다.
이렇게 하면 WIU 기능으로 포그라운드 서비스가 시작됩니다.
10분 미만의 일시적인 오류가 발생하는 동안
mediaPlaybackFGS를 활성 상태로 유지합니다.앱에 네트워크 활동으로 인한 버퍼링 문제와 같은 일시적인 오류가 있거나
AUDIOFOCUS_LOSS_TRANSIENT과 같은 예상되는 일시적인 중단이 있는 경우 재생 의도는 계속되어야 합니다. 따라서 FGS는 활성 상태로 유지되어야 합니다.재생이 끝나면 포그라운드 서비스를 중지하고 사용자가 명시적으로 재생을 재개하는 경우에만 재생을 다시 시작합니다.
재생을 종료하는 영구 신호 (예: 자동 재생이 없는 콘텐츠 완료,
AUDIOFOCUS_LOSS, UMO의 일시중지 이벤트 또는 미디어 키 이벤트) 또는 복구할 수 없는 오류의 경우 앱은 오디오 상호작용을 중단하고 포그라운드 서비스를 중지하고 미디어 세션을 종료해야 합니다. 이 모든 작업은 사용자가 원하는 백그라운드 오디오 상호작용을 '완료'하는 개념에 해당합니다. 이렇게 하면 앱에 더 이상 백그라운드 오디오 상호작용 기능이 없습니다.이후 사용자가 앱의 UI나 범용 미디어 객체 재생 버튼을 통해 명시적으로 재생을 재개하면 오디오 재생을 시작하는 인텐트가 반환되어 새로 시작된 FGS가 발생합니다.
adb 셸 명령어로 오디오 재생 동작을 테스트합니다.
Android 16 및 Android 17에서 변경사항 테스트
이 기능은 Android 16부터 이미 '경고' 수준으로 구현되어 있습니다. 즉, 앱은 adb shell cmd audio
set-enable-hardening를 사용하여 백그라운드 오디오 강화 시행을 수동으로 테스트할 수 있습니다.
Android 16을 실행하는 기기에서 시행을 사용 설정하려면 다음 명령어를 실행하세요.
adb shell cmd audio set-enable-hardening 1
Android 17을 실행하는 기기에서 시행을 사용 중지하려면 다음 명령어를 실행하세요.
adb shell cmd audio set-enable-hardening 0
또한 logcat 또는 adb 명령어 adb dumpsys audio를 사용하여 오디오 강화 시행으로 인해 앱에 자동 실패가 발생했는지 확인하는 것이 좋습니다. 그렇다면 로그에는 패키지 이름이 AudioHardening로 시작하는 항목이 있습니다.
사용 중 기능이 있는 FGS 이해
일반적으로 포그라운드 서비스 (FGS)는 앱이 포그라운드에 있는 동안 실행되어 사용자 시작 작업을 확장해야 합니다. 특정 사례의 경우 앱이 백그라운드에 있는 동안 포그라운드 서비스를 실행할 수 있습니다. 하지만 이러한 포그라운드 서비스에는 일반적으로 사용 중 (WIU) 기능이 부여되지 않습니다.
WIU는 보안 게이트 역할을 합니다. 사용자가 앱의 활동을 인식하지 못할 수 있는 경우 백그라운드에서 시작된 FGS가 특정 민감한 동작에 참여하지 못하도록 방지합니다. 위치, 카메라, 마이크와 같은 민감한 데이터에 앱이 액세스하지 못하도록 하며, Android 17부터는 일반적으로 표시되는 UI 컨텍스트가 필요한 오디오 API도 차단합니다.
다음은 유용한 참고 자료입니다.
- 표준 FGS: 앱이 표시되거나 백그라운드 활동 시작 기능이 부여된 동안 시작된 서비스에는 WIU 액세스 권한이 부여됩니다.
- 백그라운드에서 시작된 FGS (BFSL): 대부분 WIU 액세스 권한을 부여하지 않습니다. WIU를 부여하는 기본 예외는 명시적인 사용자 의도가 포함된 상호작용입니다(예: 알림 클릭, 위젯 상호작용, 외부 기기의 미디어 키 이벤트).
- 시스템에서 FGS 시작: 시스템 서버 위임 (예: Telecom Jetpack 라이브러리 사용)을 사용하여 시작된 FGS에는 WIU 액세스 권한이 부여됩니다.
백그라운드에서 포그라운드 서비스를 시작할 때 적용되는 제한사항에서 자세히 알아보세요.
영향을 받는 오디오 API의 전체 목록
오디오 기능 |
결과 |
영향을 받는 API |
오디오 재생 |
재생이 무음 처리됨 예외 없음, API에서 제공하는 실패 메시지 없음 |
(NDK) media3, Exoplayer, Oboe와 같이 재생을 관리하는 클라이언트 측 미디어 라이브러리도 영향을 받을 수 있습니다. |
오디오 포커스 요청 |
반환 값 다른 앱의 오디오 재생에 영향을 주지 않으며 포커스를 획득하지 않음 |
|
볼륨 및 벨소리 모드 API |
벨소리 모드나 볼륨에 영향을 미치지 않음 (메서드 호출이 자동으로 무시됨) 예외 없음, API에서 제공하는 실패 메시지 없음 |
|