重新想象 Windows 8 Store Apps (65) - 后台任務: 音樂的后台播放和控制
作者:webabcd
介紹
重新想象 Windows 8 Store Apps 之 后台任務
- 音樂的后台播放和控制
示例
用於保存每首音樂的相關信息的對象
BackgroundTask/SongModel.cs
/* * 用於保存每首音樂的相關信息 */ using System; using System.Threading.Tasks; using Windows.Storage; namespace XamlDemo.BackgroundTask { public class SongModel { /// <summary> /// 音樂文件 /// </summary> public StorageFile File; /// <summary> /// 藝術家 /// </summary> public string Artist; /// <summary> /// 音樂名稱 /// </summary> public string Title; public SongModel(StorageFile file) { File = file; } /// <summary> /// 加載音樂的相關屬性 /// </summary> public async Task LoadMusicPropertiesAsync() { var properties = await this.File.Properties.GetMusicPropertiesAsync(); Artist = properties.Artist; Title = properties.Title; } } }
演示如何通過 MediaControl 實現音樂的后台播放和控制
BackgroundTask/MediaControlDemo.xaml
<Page x:Class="XamlDemo.BackgroundTask.MediaControlDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.BackgroundTask" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Button Name="btnSelectFiles" Content="Select Files" Click="btnSelectFiles_Click" Margin="0 10 0 0" /> <Button Name="btnPlay" Content="Play" Click="btnPlay_Click" Margin="0 10 0 0" /> <!-- 為了使音樂可以后台播放,需要將 MediaElement 的 AudioCategory 屬性設置為 BackgroundCapableMedia --> <MediaElement Name="mediaElement" AudioCategory="BackgroundCapableMedia" AutoPlay="False" MediaOpened="mediaElement_MediaOpened" MediaEnded="mediaElement_MediaEnded" CurrentStateChanged="mediaElement_CurrentStateChanged" /> </StackPanel> </Grid> </Page>
BackgroundTask/MediaControlDemo.cs
/* * 演示如何通過 MediaControl 實現音樂的后台播放和控制 * * 注: * 1、需要在 Package.appxmanifest 中增加后台任務聲明,並勾選“音頻” * 2、需要將 MediaElement 的 AudioCategory 屬性設置為 BackgroundCapableMedia * * 另: * 按下平板上的音量鍵或者多媒體鍵盤上的相關按鍵,會彈出后台音頻的控制框,通過 MediaControl 來監聽用戶在此音頻控制框上的操作 */ using System; using System.Collections.Generic; using System.Threading.Tasks; using Windows.Media; using Windows.Storage; using Windows.Storage.Pickers; using Windows.Storage.Streams; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; namespace XamlDemo.BackgroundTask { public sealed partial class MediaControlDemo : Page { private List<SongModel> _playList = new List<SongModel>(); // 后台需要播放的音樂列表 private int _currentSongIndex = 0; // 當前播放的音樂 private bool _previousTrackPressedRegistered = false; // MediaControl 是否注冊了 PreviousTrackPressed 事件 private bool _nextTrackPressedRegistered = false; // MediaControl 是否注冊了 NextTrackPressed 事件 public MediaControlDemo() { this.InitializeComponent(); MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed; // 按下了 play/pause 鍵 MediaControl.PlayPressed += MediaControl_PlayPressed; // 按下了 play 鍵 MediaControl.PausePressed += MediaControl_PausePressed; // 按下了 pause 鍵 MediaControl.StopPressed += MediaControl_StopPressed; // 按下了 stop 鍵 MediaControl.PreviousTrackPressed += MediaControl_PreviousTrackPressed; // 按下了“上一首”鍵 MediaControl.NextTrackPressed += MediaControl_NextTrackPressed; // 按下了“下一首”鍵 MediaControl.RewindPressed += MediaControl_RewindPressed; // 按下了“快退”鍵 MediaControl.FastForwardPressed += MediaControl_FastForwardPressed; // 按下了“快進”鍵 MediaControl.SoundLevelChanged += MediaControl_SoundLevelChanged; // 音量級別發生了改變 // MediaControl.RecordPressed += MediaControl_RecordPressed; // MediaControl.ChannelDownPressed += MediaControl_ChannelDownPressed; // MediaControl.ChannelUpPressed += MediaControl_ChannelUpPressed; // MediaControl.ArtistName; // 當前播放的音樂的藝術家 // MediaControl.TrackName; // 當前播放的音樂的名稱 // MediaControl.AlbumArt; // 當前播放的音樂的專輯封面的路徑 // MediaControl.IsPlaying; // 當前音樂是否正在播放 // MediaControl.SoundLevel; // 當前播放的音樂的音量級別(Muted, Low, Full) _previousTrackPressedRegistered = true; _nextTrackPressedRegistered = true; } // 按下了音頻控制框上的 play/pause 鍵 async void MediaControl_PlayPauseTogglePressed(object sender, object e) { if (MediaControl.IsPlaying) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { mediaElement.Pause(); }); await OutputMessage("Play/Pause Pressed - Pause"); } else { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { mediaElement.Play(); }); await OutputMessage("Play/Pause Pressed - Play"); } } // 按下了音頻控制框上的 play 鍵 async void MediaControl_PlayPressed(object sender, object e) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { mediaElement.Play(); }); await OutputMessage("Play Pressed"); } // 按下了音頻控制框上的 pause 鍵 async void MediaControl_PausePressed(object sender, object e) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mediaElement.Pause(); }); await OutputMessage("Pause Pressed"); } // 按下了音頻控制框上的 stop 鍵 async void MediaControl_StopPressed(object sender, object e) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mediaElement.Stop(); }); await OutputMessage("Stop Pressed"); } // 按下了音頻控制框上的“上一首”鍵 async void MediaControl_PreviousTrackPressed(object sender, object e) { await OutputMessage("Previous Track Pressed"); if (_currentSongIndex > 0) { if (_currentSongIndex == (_playList.Count - 1)) { if (!_nextTrackPressedRegistered) { MediaControl.NextTrackPressed += MediaControl_NextTrackPressed; _nextTrackPressedRegistered = true; } } _currentSongIndex--; if (_currentSongIndex == 0) { MediaControl.PreviousTrackPressed -= MediaControl_PreviousTrackPressed; _nextTrackPressedRegistered = false; } await SetCurrentPlayingAsync(_currentSongIndex); } } // 按下了音頻控制框上的“下一首”鍵 async void MediaControl_NextTrackPressed(object sender, object e) { await OutputMessage("Next Track Pressed"); if (_currentSongIndex < (_playList.Count - 1)) { _currentSongIndex++; await SetCurrentPlayingAsync(_currentSongIndex); if (_currentSongIndex > 0) { if (!_previousTrackPressedRegistered) { MediaControl.PreviousTrackPressed += MediaControl_PreviousTrackPressed; _previousTrackPressedRegistered = true; } } if (_currentSongIndex == (_playList.Count - 1)) { if (_nextTrackPressedRegistered) { MediaControl.NextTrackPressed -= MediaControl_NextTrackPressed; _nextTrackPressedRegistered = false; } } } } // 按下了音頻控制框上的“快退”鍵,即長按“上一首”鍵 async void MediaControl_RewindPressed(object sender, object e) { await OutputMessage("Rewind Pressed"); } // 按下了音頻控制框上的“快進”鍵,即長按“下一首”鍵 async void MediaControl_FastForwardPressed(object sender, object e) { await OutputMessage("Fast Forward Pressed"); } // 音量級別發生變化時(Muted, Low, Full) async void MediaControl_SoundLevelChanged(object sender, object e) { await OutputMessage("Sound Level Changed"); } // 創建一個需要在后台播放的音樂列表 private async void btnSelectFiles_Click(object sender, RoutedEventArgs e) { FileOpenPicker openPicker = new FileOpenPicker(); openPicker.ViewMode = PickerViewMode.List; openPicker.SuggestedStartLocation = PickerLocationId.MusicLibrary; openPicker.FileTypeFilter.Add(".mp3"); openPicker.FileTypeFilter.Add(".wma"); IReadOnlyList<StorageFile> files = await openPicker.PickMultipleFilesAsync(); if (files.Count > 0) { await CreatePlaylist(files); await SetCurrentPlayingAsync(_currentSongIndex); } } // 開始播放 private async void btnPlay_Click(object sender, RoutedEventArgs e) { if (MediaControl.IsPlaying) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { mediaElement.Pause(); }); await OutputMessage("Play/Pause Pressed - Pause"); } else { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { mediaElement.Play(); }); await OutputMessage("Play/Pause Pressed - Play"); } } // MediaElement 打開文件后,如果需要播放則立刻播放 private void mediaElement_MediaOpened(object sender, RoutedEventArgs e) { if (MediaControl.IsPlaying) { mediaElement.Play(); } } // 當前音樂播放完后,轉到下一首 private async void mediaElement_MediaEnded(object sender, RoutedEventArgs e) { if (_currentSongIndex < _playList.Count - 1) { _currentSongIndex++; await SetCurrentPlayingAsync(_currentSongIndex); if (MediaControl.IsPlaying) { mediaElement.Play(); } } } // 根據前台的操作,設置 MediaControl 的 IsPlaying 屬性 private void mediaElement_CurrentStateChanged(object sender, RoutedEventArgs e) { if (mediaElement.CurrentState == MediaElementState.Playing) { MediaControl.IsPlaying = true; btnPlay.Content = "Pause"; } else { MediaControl.IsPlaying = false; btnPlay.Content = "Play"; } } // 創建音樂列表 private async Task CreatePlaylist(IReadOnlyList<StorageFile> files) { if (_previousTrackPressedRegistered) { MediaControl.PreviousTrackPressed -= MediaControl_PreviousTrackPressed; _previousTrackPressedRegistered = false; } if (_nextTrackPressedRegistered) { MediaControl.NextTrackPressed -= MediaControl_NextTrackPressed; _nextTrackPressedRegistered = false; } _playList.Clear(); _currentSongIndex = 0; if (files.Count > 0) { if (files.Count > 1) { MediaControl.NextTrackPressed += MediaControl_NextTrackPressed; _nextTrackPressedRegistered = true; } foreach (StorageFile file in files) { SongModel song = new SongModel(file); await song.LoadMusicPropertiesAsync(); _playList.Add(song); } } } // 指定當前需要播放的音樂 private async Task SetCurrentPlayingAsync(int playListIndex) { string errorMessage = null; IRandomAccessStream stream = null; try { stream = await _playList[playListIndex].File.OpenAsync(Windows.Storage.FileAccessMode.Read); await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { mediaElement.SetSource(stream, _playList[playListIndex].File.ContentType); }); } catch (Exception e) { errorMessage = e.Message; } if (errorMessage != null) { await OutputMessage(errorMessage); } MediaControl.ArtistName = _playList[playListIndex].Artist; MediaControl.TrackName = _playList[playListIndex].Title; } // 輸出信息 private async Task OutputMessage(string message) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { lblMsg.Text = message + ": " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"); }); } } }
OK
[源碼下載]