介紹
與眾不同 windows phone 7.5 (sdk 7.1) 之媒體
通過 AudioPlayerAgent 實現在背景播放音頻
樣本
示範如何通過後台代理的方式來實現音頻在背景播放
1、後台代理
MyAudioPlayerAgent/AudioPlayer.cs
/* * 本例示範如何播放後台音頻(以 AudioPlayerAgent 為例,另 AudioStreamingAgent 用於流式播放音頻) * 建議使用 AudioPlaybackAgent 類型的模板建立此項目 * * BackgroundAgent - 後台代理類,抽象類別,它是 ScheduledTaskAgent、AudioPlayerAgent 和 AudioStreamingAgent 的基類 * NotifyComplete() - 用於通知系統,代理已經完成了當前的任務,調用此方法後,系統才會去準備執行下一次任務 * Abort() - 用於通知系統,放棄此次和以後的任務 * OnCancel() - 後台代理被取消時所執行的方法(由系統調用,比如後台代理轉到休眠狀態或終止狀態前會調用此方法) * * AudioPlayerAgent - 後台播放音訊代理類 * OnError() - 當播放中出現錯誤時,系統會調用此方法 * OnPlayStateChanged() - 當播放狀態發生改變時,系統會調用此方法(錯誤狀態除外) * OnUserAction() - 當程式改變播允許存取為時,系統會調用此方法 * * PlayState - Microsoft.Phone.BackgroundAudio.PlayState 枚舉 * Unknown, Stopped, Paused, Playing, BufferingStarted, BufferingStopped, TrackReady, TrackEnded, Rewinding, FastForwarding, Shutdown, Error * * UserAction - Microsoft.Phone.BackgroundAudio.UserAction 枚舉 * Stop, Pause, Play, SkipNext, SkipPrevious, FastForward, Rewind, Seek * * AudioTrack - 音頻對象 * Source - 音訊地址,遠程地址或隔離儲存區 (Isolated Storage)地址均可 * Title - 音頻名稱 * Duration - 音頻時間長度 * Album - 專輯名稱 * AlbumArt - 專輯封面的 Uri 地址,遠程地址或隔離儲存區 (Isolated Storage)地址均可,如果使用隔離儲存區 (Isolated Storage)地址則其目錄必須是 Shared/Media * Artist - 藝術家 * PlayerControls - 鎖屏等狀態下的播放器控制項顯示(Microsoft.Phone.BackgroundAudio.EnabledPlayerControls 枚舉) * None = 0, SkipNext = 1, SkipPrevious = 2, FastForward = 4, Rewind = 8, Pause = 16, All = 31 * Tag - 任意內容,即為 AudioTrack 綁定一個上下文資料 * BeginEdit() - 將 AudioTrack 設定為編輯狀態(如果需要修改 AudioTrack 的屬性則需要將 AudioTrack 設定為編輯狀態) * EndEdit() - 結束 AudioTrack 的編輯狀態 */ using System; using System.Windows; using Microsoft.Phone.BackgroundAudio; using System.Collections.Generic; namespace MyAudioPlayerAgent { public class AudioPlayer : AudioPlayerAgent { // 播放清單 private static List<AudioTrack> _playList = new List<AudioTrack> { new AudioTrack(new Uri("SuperMario.mp3", UriKind.Relative), "title", "artist", "album", null, null, EnabledPlayerControls.Pause), new AudioTrack(new Uri("http://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute), "標題", "藝術家", "專輯", null, null, EnabledPlayerControls.All) }; // 當前播放的 Track 在整個播放清單中的位置 private static int _currentTrackNumber = 0; /* * _classInitialized - 用於標記 AudioPlayer 是否已經被初始化 * 標記成 volatile 是為了避免編譯器認為此欄位無外部修改,而將其最佳化放入寄存器(標記成 volatile 的欄位只會放在記憶體中) * 一般來說,多任務環境下各任務間共用的欄位應該被標記為 volatile */ private static volatile bool _classInitialized; public AudioPlayer() { if (!_classInitialized) { _classInitialized = true; Deployment.Current.Dispatcher.BeginInvoke(delegate { Application.Current.UnhandledException += AudioPlayer_UnhandledException; }); } } private void AudioPlayer_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); } } // 播放狀態發生改變時所調用的方法 protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState) { switch (playState) { case PlayState.TrackReady: player.Play(); break; case PlayState.TrackEnded: PlayNextTrack(player); break; case PlayState.Playing: break; case PlayState.Paused: break; case PlayState.Stopped: break; case PlayState.BufferingStarted: break; case PlayState.BufferingStopped: break; case PlayState.Rewinding: break; case PlayState.FastForwarding: break; case PlayState.Shutdown: break; case PlayState.Unknown: break; } NotifyComplete(); } // 當程式改變播允許存取為時所調用的方法 protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param) { switch (action) { case UserAction.Play: PlayTrack(player); break; case UserAction.SkipPrevious: PlayPreviousTrack(player); break; case UserAction.SkipNext: PlayNextTrack(player); break; case UserAction.Rewind: player.Rewind(); break; case UserAction.FastForward: player.FastForward(); break; case UserAction.Seek: player.Position = (TimeSpan)param; break; case UserAction.Pause: player.Pause(); break; case UserAction.Stop: player.Stop(); break; } NotifyComplete(); } // 播放下一個 Track private void PlayNextTrack(BackgroundAudioPlayer player) { if (++_currentTrackNumber >= _playList.Count) _currentTrackNumber = 0; PlayTrack(player); } // 播放上一個 Track private void PlayPreviousTrack(BackgroundAudioPlayer player) { if (--_currentTrackNumber < 0) _currentTrackNumber = _playList.Count - 1; PlayTrack(player); } // 播放當前 Track private void PlayTrack(BackgroundAudioPlayer player) { player.Track = _playList[_currentTrackNumber]; } // 出現異常時所調用的方法 protected override void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal) { if (isFatal) Abort(); else NotifyComplete(); } // 當後台代理轉到休眠狀態或終止狀態前,系統會自動調用此方法,需要在 5 秒內執行完畢 protected override void OnCancel() { } } } /* * 主程式引用此項目後,會在 manifest 中添加如下資訊: * <ExtendedTask Name="BackgroundTask"> * <BackgroundServiceAgent Specifier="AudioPlayerAgent" Name="MyAudioPlayerAgent" Source="MyAudioPlayerAgent" Type="MyAudioPlayerAgent.AudioPlayer" /> * </ExtendedTask> */