共用方式為


概觀:背景音訊 (Windows Phone 市集應用程式)(HTML)

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

您可以撰寫在背景播放音訊的 Windows Phone 8.1 應用程式。這表示即使使用者按裝置上的 [返回] 按鈕或 [開始]**** 按鈕離開應用程式,您的應用程式仍然可以繼續播放音訊。本文討論背景音訊應用程式的元件,以及它們如何搭配運作。

背景音訊播放案例包含:

  • 長時間執行的播放清單使用者會短暫叫用前景應用程式來選取和開始播放清單,完成這些動作後,使用者預期播放清單會在背景持續播放。
  • 使用工作切換器使用者會短暫叫用前景應用程式來開始播放音訊,然後使用工作切換器,切換到另一個開啟的應用程式。使用者預期音訊會在背景持續播放。

秘訣  您可以下載 Windows Phone 8.1 背景音訊範例的程式碼,該範例實作本概觀中討論的程式碼。

 

背景音訊架構

背景音訊應用程式使用背景代理程式。不過,在 Windows Phone 8.1 的背景播放音訊與在 Windows 8 播放背景音訊的方法不同。模型也與舊版 Windows Phone 所用的背景音訊代理程式不同。

重要事項  

您可以使用 JavaScript 撰寫背景音訊應用程式。不過,Windows Phone 8.1 不允許 JavaScript 在背景程序中執行。這表示您可以用 JavaScript 撰寫前景應用程式與 UI,但必須以 C# 或 C++ 撰寫背景工作。適用於 Windows Phone 8.1 背景音訊的範例提供的 JavaScript 應用程式範例,使用 C# 背景代理程式支援背景音訊。

 

Windows.Media.Playback 命名空間引進了一般音訊 API,這些 API 即使在前景也能播放音樂,但它們的主要用途是在背景播放音訊。使用這個 API 時,所有播放都是透過單一全域 MediaPlayer 執行。您的背景音訊應用程式會將命令傳送到媒體播放程式,以設定目前的曲目、開始播放、暫停、向前快轉、倒轉等。您可以呼叫 MediaPlayer 類別上的方法來執行這個動作。媒體播放程式執行個體物件透過 BackgroundMediaPlayer.Current 屬性進行存取,與全域媒體播放程式通訊,以操控音訊播放。

您不能建立新的 MediaPlayer 執行個體。

使用 SystemMediaTransportControls 類別,引發萬用音量控制 (UVC) 所使用的事件。UVC 是當應用程式使用者按裝置上的音量控制時出現的 UI。您使用 SystemMediaTransportControls 來操控媒體播放程式。除了從應用程式開始播放音訊,您還能夠控制音訊播放。例如,在應用程式中使用 SystemMediaTransportControls 將事件傳送到 IBackgroundTask,而您可以實作播放清單邏輯。本主題稍後會有更多關於 IBackgroundTask 的討論。

下圖是非常簡單的系統設計檢視。應用程式背景播放包含兩個處理程序。第一個處理程序是在前景執行的主應用程式 (包含 UI)。第二個處理程序是背景播放工作,包含音訊播放機器,以及一些選擇性的應用程式邏輯。作業系統會依據資源需求暫停或終止前景處理程序。背景處理程序則會繼續執行。

音訊播放在背景處理程序中進行時,前景處理程序可透過 Proxy 物件存取所有資訊。前景處理程序可以管理背景處理程序中 MediaPlayer 執行個體的屬性。前景應用程式可以收到媒體特定事件的通知,如 MediaOpenedMediaEndedMediaFailed。當前景處理程序終止或應用程式暫停時,媒體會持續播放。

背景音訊架構

系統媒體傳輸控制項

SystemMediaTransportControls 是 Windows 8.1 引進的一組新的 API。Windows Phone 8.1 也會實作這個類別,但因為 Windows Phone 只有一個全域音量控制,因此一次只能與一個處理程序互動。在 MediaPlayer API 的情況下,定義背景處理程序的執行個體和所有處理常式非常重要。這可確保當前景應用程式終止時,連線會繫結到正確的處理程序。

在工作間傳送訊息

有時候您會想在背景音訊應用程式的兩個處理程序間進行通訊。例如,開始播放新曲目時,您可能希望背景工作通知前景工作,然後將新的歌曲標題傳送到前景工作以顯示在畫面上。簡單的通訊機制可同時在前景和背景處理程序中引發事件。SendMessageToForegroundSendMessageToBackground 方法會個別叫用對應工作中的事件。在接收工作中,資料可以引數的形式傳送到事件處理常式。使用名為 ValueSet 的新類別傳送資料。此類別是一個字典,其中包含的字串為索引鍵,而其他值類型則是值。您可以傳送簡易的值類型,例如 intstringbool 等。

背景工作週期

背景工作的週期與應用程式播放音樂的能力有很緊密的關係。例如,當使用者暫停音訊播放時,系統可能會根據情況終止或取消您的應用程式。

您的背景工作會在您的應用程式存取前景應用程式碼中的 BackgroundMediaPlayer.Current 時,或在您登錄 MessageReceivedFromBackground 事件的處理常式時首次啟動,以較早發生者為準。為確保在呼叫 IBackgroundTask.Run 方法時建立通訊通道,您必須在第一次存取 BackgroundMediaPlayer.Current 屬性之前先登錄 MessageReceivedFromBackground 事件。 您的應用程式必須等到背景工作開始執行時,才能嘗試開始播放任何音訊。這樣您才可以訂閱媒體事件。

若要讓背景工作持續執行,您的應用程式必須取得 Run 方法的 BackgroundTaskDeferral,並在工作執行個體收到 CanceledCompleted 事件時呼叫 BackgroundTaskDeferral.Complete。不要在 Run 方法中持續等待,因為這樣會消耗資源,而且可能讓您的應用程式背景工作終止。

Run 方法完成且沒有要求延遲時,您的背景工作會取得 Completed 事件。在某些情況下,當您的應用程式取得 Canceled 事件,稍後也可能會收到 Completed 事件。

在下列情況下可能會取消背景工作:

  • 含有音訊播放功能的新應用程式開始執行。
  • 背景工作已啟動但尚未播放音樂,然後前景應用程式就暫停。
  • 背景工作啟動執行一段時間之後,播放暫停且前景應用程式暫停。使用者或其他媒體中斷 (例如來電或 VoIP 通話) 都可讓播放暫停。如果來電或 VoIP 通話在五分鐘內結束,您的應用程式會收到 Run 通知,以及 SystemMediaTransportControlsButtonPressedEventArgs 中指出的 SystemMediaTransportControlsButton.Play 按鈕。如果沒有,使用者需要使用 UVC 明確開始播放。UVC 不會遺失它的狀態。 但是,當使用者按 [播放] 按鈕時,即會重新啟動背景工作。接著,您會取得 Run 方法呼叫和 SystemMediaTransportControlsButton.Play 通知。

在下列情況下會無預警終止背景工作:

  • 收到 VoIP 通話,但沒有足夠的記憶體。
  • 違反資源原則。
  • 工作取消或完成沒有正常結束。

背景音訊最佳做法

媒體管線實際上是不同步的,這表示觸發的事件只能保證這些事件會發生,但無法保證這些事件的順序。例如,當您的應用程式從遠端來源取得音訊檔,應用程式會取得各種狀態變更事件,例如 StartingPausedClosed 等。但是,不一定每次都會以相同的順序呼叫這些處理常式。您不應太過依賴 CurrentStateChanged 處理常式中的 CurrentState 值。

MediaOpened 是非常重要的事件,且扮演多個角色。如果您將 AutoPlay 設為 false,且設定了 MediaPlayer 的來源,您仍然會收到 MediaOpened。這代表已初始化媒體管線,而且您的媒體已可以開始播放。設定來源後,會自動開始媒體播放。您不需要在設定來源後呼叫 Play。還有另一個很非常棒的技術,那就是在媒體就緒後明確地播放。若要這樣做,將 AutoPlay 設為 false,並在 MediaOpened 處理常式中明確呼叫 Play

您可以透過呼叫 SetUriSourceSetFileSourceSetMediaSourceSetStreamSource,將媒體來源設為多種不同的內容類型。MediaPlayer 也能夠播放受保護的內容。除了設定 URI 來源,系統還需依賴記憶體中執行的應用程式物件或應用程式程式碼。此外,背景處理程序也無法感知前景工作的處理程序記憶體。因此,請確定已定義所有物件,讓它們只在背景處理程序設定來源。如果您的應用程式嘗試在前景處理程序設定 URI 以外的來源,系統會擲回 InvalidCastException

BackgroundMediaPlayer.Shutdown 關閉媒體管線,並從記憶體釋放 MediaPlayer 物件。如果您嘗試在呼叫 Shutdown 後再次存取 BackgroundMediaPlayer.Current 參照,會收到錯誤。Shutdown 是應用程式在工作取消時用來清理媒體管線的。

當您的應用程式暫停後,記得取消訂閱 MediaPlayer 事件,否則您或許會遇到可能導致前景處理程序終止的未預期活動。不過,這不表示前景處理程序會從工作切換器中消失,使用者仍然可以回到應用程式。應用程式繼續後,如果您仍然有已暫停 MediaPlayer 的參照,若背景音訊工作已取消且媒體管線已關閉,則會擲回錯誤。

相關主題

Windows Phone 8.1 背景音訊範例

如何偵錯背景工作