[源码下载]

重新想象 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. 【转】 IOS开发xcode报错之has been modified since the precompiled header was built

    本文转载自  IOS开发xcode报错之has been modified since the precompiled header was built 其实我是升级xcode到4.6.3的时候遇到的 ...

  2. 使用git提交内容到网盘

    1.创建版本库(注意勾选纯版本库的选项) 2.客户端获取版本库代码 3.提交及获取 master是git默认的主要分支(主干),适合单人独自开发.多人开发时可以给每个人创建一个分支 参考资料: htt ...

  3. WPF读写config配置文件

    1. 在你的工程中,添加app.config文件.文件的内容默认为: 1 <?xml version="1.0" encoding="utf-8" ?&g ...

  4. VS2010+Selenium测试脚本设计

    VS2010+Selenium测试脚本设计 http://www.docin.com/p-755903506.html

  5. 关于织梦系统不支持php中GD库的问题

    大多数人在显成的PHP的CMS时,如织梦CMS,安装的时候不支持GD库,就导致整个网站的验证码不显示,以下是个人对此类问题的解决办法: 1.首先找到wamp的安装目录,找到PHP的文件夹,打开php. ...

  6. HTML5[6]:多行文本显示省略号

    CSS3新增text-overflow: ellipse; 只支持单行文本 如果是多行文本, 在无法完全显示的情况下,可以按下面这样写: overflow:hidden; display: -webk ...

  7. Qt4.8.6 Embedded Linux 的编译与移植

    最近买了个飞凌ok6410 的开发板,于是在其中搭建qt4.8.6运行环境.费了两三天时间,主要还是对Linux系统的生疏,在一些问题上徘徊很久,在这里做一些过程笔记.烧写ARM-Linux系统,根据 ...

  8. AssetBundle系列——共享资源打包/依赖资源打包

    有人在之前的博客中问我有关共享资源打包的代码,其实这一块很简单,就两个函数: BuildPipeline.PushAssetDependencies():依赖资源压栈: BuildPipeline.P ...

  9. 前端模块化:RequireJS

    前言 前端模块化能解决什么问题? 模块的版本管理 提高可维护性 -- 通过模块化,可以让每个文件职责单一,非常有利于代码的维护 按需加载 -- 提高显示效率 更好的依赖处理 -- 传统的开发模式,如果 ...

  10. NopCommerce之任务执行

    NOP任务提供两种:手动执行(立即)和定时执行两种. 首先来说下手动任务执行过程,下图是NOP定时任务管理界面: 从上面可以看出,我们可以选择具体的任务来手动执行任务(立即执行),当点击[立即执行]按 ...