[源码下载]

重新想象 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 = ; // 当前播放的音乐 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 > )
{
if (_currentSongIndex == (_playList.Count - ))
{
if (!_nextTrackPressedRegistered)
{
MediaControl.NextTrackPressed += MediaControl_NextTrackPressed;
_nextTrackPressedRegistered = true;
}
} _currentSongIndex--; if (_currentSongIndex == )
{
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 - ))
{
_currentSongIndex++;
await SetCurrentPlayingAsync(_currentSongIndex); if (_currentSongIndex > )
{
if (!_previousTrackPressedRegistered)
{
MediaControl.PreviousTrackPressed += MediaControl_PreviousTrackPressed;
_previousTrackPressedRegistered = true;
} } if (_currentSongIndex == (_playList.Count - ))
{
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 > )
{
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 - )
{
_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 = ; if (files.Count > )
{
if (files.Count > )
{
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
[源码下载]

重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制的更多相关文章

  1. 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务

    [源码下载] 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后 ...

  2. 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传

    [源码下载] 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 后台 ...

  3. 重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知

    [源码下载] 重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 推送通 ...

  4. 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel)

    [源码下载] 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel) 作者:webabcd 介绍重新想象 Windows 8 Store ...

  5. 重新想象 Windows 8 Store Apps 系列文章索引

    [源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...

  6. 重新想象 Windows 8 Store Apps (3) - 控件之内容控件: ToolTip, Frame, AppBar, ContentControl, ContentPresenter; 容器控件: Border, Viewbox, Popup

    原文:重新想象 Windows 8 Store Apps (3) - 控件之内容控件: ToolTip, Frame, AppBar, ContentControl, ContentPresenter ...

  7. 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute

    [源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...

  8. 重新想象 Windows 8 Store Apps (59) - 锁屏

    [源码下载] 重新想象 Windows 8 Store Apps (59) - 锁屏 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 锁屏 登录锁屏,获取当前程序的锁 ...

  9. 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth

    [源码下载] 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 ...

随机推荐

  1. Asp.net Core WebApi 支持json/xml格式的数据返回

    Asp.net core 在做webapi项目的时候,默认是只返回json格式的数据的,如果想要开启xml数据返回,需要在startup里配置如下: public void ConfigureServ ...

  2. iOS-Xcode上传后iTunes Connect构建版本不显示

    在升级到Xcode8版本以后大多数人会碰到这个问题-开开心心开发好一款app以后上传到iTunes后台提交审核,然而iTunes Connect后台活动栏里没有出现我们上传的app,确切的说是显示一会 ...

  3. 如何查看 exec sp_execute 10 XXX, XXXX的RPC事件 内容

    使用事件探查器经常能捕捉到类似于exec sp_execute 10 XXX, XXXX的RPC事件. 我想问下从哪里可以看到存储过程sp_execute 10的内容呢?? 方法如下: 在新建的pro ...

  4. jquery-migrate.js

    这个插件可以用来检测和恢复在jQuery1.9版本中已删除或已过时的API.

  5. Node.js 的module 系统

    相较于原生的JavaScript,不同的JavaScript文件之间很难共享变量.有鉴于此,Node.js在JavaScript的基础上进行了扩充,引入了require,exports,module三 ...

  6. MVC学习中遇到问题

    1:无法连接到localdb数据库 解决方案:下载localdb安装软件 2:运行程序时提示数据库已存在,请更改连接名 解决方案:因为在两个不同的解决方案中使用了同样的连接字符串造成生成了同样的数据库 ...

  7. FLEX自定义事件

    有时候我们需要让两个组件之间实现联动,并且在其中传递数据,自定义事件机制可以帮助我们比较优雅的实现这种需要. 下面的例子,是打算实现一个列表和一个编辑框的联动. 编辑框代码 <?xml vers ...

  8. aliyun ubuntu mysql

    http://www.codingyun.com/article/38.html ------------ python install mysql module ubuntu下mysql-pytho ...

  9. 解决 Tomcat 无法绑定 80 端口的问题,以及 Tomcat 配置虚拟目录、二级域名等

    问题 今天安装完 Tomcat,安装时把 Tomcat 默认的 HTTP/1.1 Connector Port 从 8080 改为了 7080,启动 Tomcat,在浏览器中输入 Http://loc ...

  10. WebStorm 8 注册码

    UserName:William ===== LICENSE BEGIN ===== 45550-12042010 00001SzFN0n1bPII7FnAxnt0DDOPJA INauvJkeVJB ...