개요: 백그라운드 오디오(Windows Phone 스토어 앱)(HTML)

[ 이 문서는 Windows 런타임 앱을 작성하는 Windows 8.x 및 Windows Phone 8.x 개발자를 대상으로 합니다. Windows 10용으로 개발하는 경우에는 최신 설명서를 참조하세요.]

백그라운드에서 오디오를 재생하는 Windows Phone 8.1용 앱을 작성할 수 있습니다. 즉, 사용자가 장치에서 뒤로 버튼이나 시작 버튼을 눌러 앱을 나간 후에도 앱이 계속해서 오디오를 재생할 수 있습니다. 이 문서에서는 백그라운드 오디오 앱의 구성 요소와 해당 구성 요소가 함께 작동하는 방식에 대해 설명합니다.

백그라운드 오디오 재생에 대한 시나리오는 다음과 같습니다.

  • 오래 실행되는 재생 목록 사용자가 간단하게 포그라운드 앱을 표시하여 재생 목록을 선택하고 시작할 수 있으며, 그 후 사용자는 예상대로 백그라운드에서 재생 목록을 계속 재생할 수 있습니다.
  • 작업 전환기 사용 사용자가 간단하게 포그라운드 앱을 표시하여 오디오 재생을 시작한 다음 작업 전환을 사용하여 열려 있는 다른 앱으로 전환할 수 있습니다. 사용자는 예상대로 백그라운드에서 오디오를 계속 재생할 수 있습니다.

  이 개요에 설명된 코드를 구현하는 Windows Phone 8.1용 백그라운드 오디오 샘플 코드를 다운로드할 수 있습니다.

 

백그라운드 오디오 아키텍처

백그라운드 앱은 백그라운드 에이전트를 사용합니다. 그러나 Windows Phone 8.1의 백그라운드에서 오디오를 재생하는 것은 Windows 8에서 백그라운드 오디오 재생하는 것과는 다릅니다. 모델도 Windows Phone의 이전 버전에서 사용되는 백그라운드 오디오 에이전트와 다릅니다.

중요  

JavaScript를 사용하여 백그라운드 오디오 응용 프로그램을 작성할 수 있습니다. 하지만 Windows Phone 8.1에서는 JavaScript가 백그라운드 프로세스에서 실행될 수 없습니다. 다시 말해서, 포그라운드 앱과 UI는 JavaScript로 작성할 수는 있지만 백그라운드 작업은 반드시 C# 또는 C++로 작성해야 한다는 뜻입니다. Windows Phone 8.1 용 백그라운드 오디오 샘플에서는 C# 백그라운드 에이전트를 사용하여 백그라운드 오디오를 지원하는 JavaScript 앱의 예를 제공합니다.

 

Windows.Media.Playback 네임스페이스에서 일반 오디오 API를 제공하며 이 네임스페이스를 사용하여 포그라운드에서도 음악을 재생할 수 있지만 기본 목적은 백그라운드에서 오디오를 재생하는 것입니다. 이 API를 사용하는 경우 단일 글로벌 MediaPlayer를 통해 모든 재생이 수행됩니다. 백그라운드 오디오 앱은 현재 트랙 설정, 재생 시작, 일시 중지, 빨리 감기, 되감기 등에 대한 명령을 미디어 플레이어에 보냅니다. 이 작업을 하려면 MediaPlayer 클래스에서 메서드를 호출합니다. 그러면 BackgroundMediaPlayer.Current 속성을 통해 액세스하는 미디어 플레이어 인스턴스 개체가 글로벌 미디어 플레이어와 통신하여 오디오 재생을 조작합니다.

MediaPlayer의 새 인스턴스를 만들 수는 없습니다.

SystemMediaTransportControls 클래스를 사용하여 UVC(Universal Volume Control)에서 사용되는 이벤트를 발생시킵니다. UVC는 앱 사용자가 장치에서 볼륨 컨트롤을 누르면 나타나는 UI입니다. SystemMediaTransportControls를 사용하여 미디어 플레이어를 조작합니다. 앱에서 오디오 재생을 시작할 뿐만 아니라 오디오 재생을 제어할 수도 있습니다. 예를 들어 앱에서 SystemMediaTransportControls를 사용하여 이벤트를 IBackgroundTask로 전송하면 재생 목록 논리를 구현할 수 있습니다. 이 항목의 뒷부분에서 IBackgroundTask에 대해 자세히 설명합니다.

다음 다이어그램은 시스템 설계 방법에 대한 간단한 보기입니다. 백그라운드 재생을 수행하는 앱은 두 개의 프로세스로 구성됩니다. 첫 번째 프로세스는 포그라운드에서 실행되는, UI가 포함된 메인 앱입니다. 두 번째 프로세스는 오디오 재생 기계 장치가 포함된 백그라운드 재생 작업 및 선택적으로 일부 앱 논리입니다. 포그라운드 프로세스는 리소스 요구 사항에 따라 운영 체제에 의해 일시 중단되거나 종료됩니다. 백그라운드 프로세스는 계속 실행 됩니다.

오디오 재생이 백그라운드 프로세스에서 수행되는 동안 포그라운드 프로세스는 프록시 개체를 통해 모든 정보에 액세스할 수 있습니다. 포그라운드 프로세스는 백그라운드 프로세스의 MediaPlayer 인스턴스 속성을 관리할 수 있습니다. 포그라운드 앱은 MediaOpened, MediaEndedMediaFailed 같은 미디어 관련 이벤트에 대한 알림을 수신할 수 있습니다. 포그라운드 프로세스가 종료되거나 앱이 일시 중단되는 경우에도 미디어가 계속 재생됩니다.

백그라운드 오디오 아키텍처

시스템 미디어 전송 컨트롤

SystemMediaTransportControls는 Windows 8.1에서 소개된 새로운 API 집합입니다. Windows Phone 8.1도 이 클래스를 구현하지만 Windows Phone에는 하나의 글로벌 볼륨 컨트롤이 있으므로 한 번에 하나의 프로세스만 상호 작용할 수 있습니다. MediaPlayer API의 컨텍스트에서 인스턴스와 모든 처리기를 백그라운드 프로세스에서 정의하는 것이 매우 중요합니다. 이렇게 해야 포그라운드 앱이 종료된 경우 연결이 적합한 프로세스에 바인딩됩니다.

작업 간에 메시지 보내기

백그라운드 오디오 앱의 두 프로세스 간에 통신이 필요한 경우가 있습니다. 예를 들어 새 트랙 재생이 시작될 때 백그라운드 작업이 포그라운드 작업에 알림을 보낸 다음 새 노래 제목을 포그라운드 작업에 보내 화면에 표시하도록 할 수 있습니다. 간단한 통신 메커니즘을 사용하여 포그라운드 및 백그라운드 프로세스에서 이벤트를 발생시킬 수 있습니다. SendMessageToForegroundSendMessageToBackground 메서드는 각각 해당 작업에서 이벤트를 호출합니다. 수신 작업에서 데이터를 이벤트 처리기에 인수로 전달할 수 있습니다. ValueSet라는 새 클래스를 사용하여 데이터를 전달합니다. 이 클래스는 문자열이 키로 포함되고 기타 값 유형이 값으로 포함된 사전입니다. int, string, bool 등의 간단한 값 유형을 전달할 수 있습니다.

백그라운드 작업 수명 주기

백그라운드 작업의 수명은 앱의 음악 재생 기능과 밀접한 관련이 있습니다. 예를 들어 사용자가 오디오 재생을 일시 중지하면 시스템에서는 상황에 따라 앱을 종료하거나 취소할 수 있습니다.

백그라운드 작업은 앱이 포그라운드 앱 코드의 BackgroundMediaPlayer.Current에 처음 액세스할 때와 MessageReceivedFromBackground 이벤트에 대한 처리기를 등록할 때 중에서 먼저 일어나는 작업 후에 시작됩니다. IBackgroundTask.Run 메서드가 호출될 때 통신 채널이 설정되도록 하려면 처음에 BackgroundMediaPlayer.Current 속성에 액세스하기 전에 MessageReceivedFromBackground 이벤트를 등록해야 합니다. 앱은 오디오 재생을 시작하기 전에 백그라운드 작업이 실행될 때까지 기다려야 합니다. 이 방법으로 미디어 이벤트를 구독할 수 있습니다.

백그라운드 작업을 계속 유지하려면 앱이 Run 메서드로 BackgroundTaskDeferral을 가져오고 작업 인스턴스가 Canceled 또는 Completed 이벤트를 수신할 때 BackgroundTaskDeferral.Complete를 호출해야 합니다. 리소스가 사용되고 앱의 백그라운드 작업이 종료될 수 있으므로 Run 메서드에서 계속 기다리지는 마세요.

백그라운드 작업은 Run 메서드가 완료되고 지연이 요청되지 않을 때 Completed 이벤트를 가져옵니다. 경우에 따라 앱이 Canceled 이벤트를 가져올 때 Completed 이벤트도 따라올 수 있습니다.

백그라운드 작업은 다음과 같은 경우 취소될 수 있습니다.

  • 오디오 재생 접근 권한 값이 있는 새 앱이 시작될 경우
  • 백그라운드 작업이 시작되었으나 음악이 아직 재생되지 않고 이후 포그라운드 앱이 일시 중단된 경우
  • 백그라운드 작업이 시작되고 재생이 일시 중지되고 포그라운드 앱이 일시 중단된 때부터 얼마 후 사용자나 수신 전화 통화 또는 VoIP 전화와 같은 기타 미디어 중단에 의해 재생이 일시 중지될 수 있습니다. 전화 통화나 VoIP 전화가 5분 내에 종료되면 앱은 SystemMediaTransportControlsButtonPressedEventArgs에 지정된 SystemMediaTransportControlsButton.Play 버튼이 포함된 Run 알림을 수신합니다. 종료되지 않을 경우 사용자는 UVC를 사용하여 명시적으로 재생을 시작해야 합니다. UVC의 상태가 손실되지는 않습니다. 그러나 사용자가 재생 버튼을 누르면 백그라운드 작업이 다시 시작됩니다. 그런 다음 Run 메서드 호출과 SystemMediaTransportControlsButton.Play 알림을 받습니다.

백그라운드 작업은 다음과 같은 경우 경고 없이 종료될 수 있습니다.

  • VoIP 전화가 들어오고 메모리가 충분하지 않은 경우
  • 리소스 정책에 위반된 경우
  • 작업 취소 또는 완료가 정상적으로 종료되지 않은 경우

백그라운드 오디오 모범 사례

미디어 파이프라인은 특성상 비동기적이며, 이는 발생한 이벤트가 해당 이벤트의 발생만 보장하며 이벤트 순서는 보장하지 않음을 의미합니다. 예를 들어 앱이 원격 소스에서 오디오 파일을 가져오는 경우 앱은 Starting, Paused, Closed 등 다양한 상태 변경 이벤트를 가져옵니다. 이러한 처리기가 매번 같은 순서로 호출되지는 않습니다. CurrentStateChanged 처리기의 CurrentState 값에 크게 의존하지 않아야 합니다.

MediaOpened는 매우 중요한 이벤트이며 여러 역할을 수행합니다. AutoPlayfalse로 설정하고 MediaPlayer에 대한 소스를 설정하는 경우에도 MediaOpened가 수신됩니다. 이는 미디어 파이프라인이 시작되고 미디어가 재생 준비가 되었음을 나타냅니다. 소스를 설정하면 미디어 재생이 자동으로 시작됩니다. 소스를 설정한 후 Play를 호출할 필요가 없습니다. 미디어가 준비되었을 때 명시적으로 재생하는 것도 매우 좋은 방법입니다. 이 작업을 수행하려면 AutoPlayfalse로 설정하고 MediaOpened 처리기에서 명시적으로 Play를 호출합니다.

SetUriSource, SetFileSource, SetMediaSource 또는 SetStreamSource를 호출하여 미디어 소스를 다양한 콘텐츠 유형으로 설정할 수 있습니다. MediaPlayer에는 보호된 콘텐츠를 재생하는 기능도 있습니다. URI 소스 설정 이외에 시스템은 메모리에서 실행되는 앱 개체나 앱 코드에 따라 달라집니다. 또한 백그라운드 프로세스는 포그라운드 작업의 프로세스 메모리를 인식하지 못합니다. 따라서 백그라운드 프로세스에서만 소스를 설정하도록 모든 개체를 정의해야 합니다. 앱이 포그라운드 프로세스에서 URI 이외의 소스를 설정하려고 하면 InvalidCastException이 발생합니다.

BackgroundMediaPlayer.Shutdown은 미디어 파이프라인을 닫고 MediaPlayer 개체를 메모리에서 해제합니다. Shutdown을 호출한 후 BackgroundMediaPlayer.Current에 대한 참조에 다시 액세스하려고 하면 오류가 발생합니다. Shutdown은 앱 작업이 취소된 후 앱이 미디어 파이프라인을 정리하는 데만 사용됩니다.

앱이 일시 중단될 경우 MediaPlayer 이벤트 구독을 취소해야 합니다. 그렇지 않으면 포그라운드 프로세스가 종료될 수 있는 예상치 못한 활동이 발생할 수 있습니다. 그러나 이는 포그라운드 프로세스가 작업 전환기에서 벗어난다는 의미는 아니며 사용자는 계속해서 앱으로 돌아갈 수 있습니다. 앱이 다시 시작될 때 일시 중단된 MediaPlayer에 대한 참조를 유지하고 있으면 백그라운드 오디오 작업이 취소되고 미디어 파이프라인이 종료된 경우 오류가 발생합니다.

관련 항목

Windows Phone 8.1용 백그라운드 오디오 샘플

백그라운드 작업을 디버그하는 방법