新时尚Windows8开发(26):后台播放Musics

2024-03-20 01:08

本文主要是介绍新时尚Windows8开发(26):后台播放Musics,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要说这Windows Store应用像啥,像网页,而且还全屏的,所以,这和传统桌面应用就有着明显的差异,在同一时刻就只有一个应用在前台运行,对,和手机一样。

故今天我们的话题,本质上是讨论媒体播放的,不过,如果不顺便考虑一下后台播放,感觉有点……你想,当你启动一个播放音乐的应用,正听着很美的音乐,突然我想看看我微博上有啥更新,回到“开始”屏幕,启动一下微博应用。我靠!音乐停了,你想这多没意思啊。

所以啊,当我们希望开发一个播放音乐的应用时,支持后台播放那可是头等大事。

 

好了,牛皮就不吹了,开始说正题。

你说在应用程序中如何播放多媒体,这个应该各位都会,当然我这里指的是XAML中的,HTML5本身就支持多媒体播放。是的,MediaElement,想起来了吧,这位老哥们儿,你不可能不认识D,在玩WPF/Silverlight/Windows Phone等开发的时候,你一定和她亲密接触过的。这控件用起来也很简单,给她一个播放源就可以,就好像一位演技很好的MM,你只需为她简单妆扮,上了舞台就发挥自如。

<MediaElement Source="abcd.mp3" />

可能有时候会设置一下音量什么的,或者把AutoPlay设置为True,这使得这个控件在设置源后便马上播放。

 

这个,我相信大家都会,这里就不多重复了,不然又有人说“这和Win8有毛关系,这不是WPF中的XAML吗?”是的,XAML就是好,跨项目应用;完美的集成性就是好,学会一个知识,可以迅速迁移到其他知识;统一性就是好,专心做程序,不必须要冲突等问题浪费青春。


那么,如何实现后台播放呢,我们来做一做实验吧。如何新建项目我就省略了,我相信这操作连鸵鸟都会了。

1、打开清单文件编辑器,切换到“功能”选项卡,选上“音乐库”,我们待会儿要用。

 

2、切换到“声明”选项卡,在下拉列表中选择“后台任务”,并点击“添加”按钮;添加后,在右侧窗格中,勾选“音频”,并填上入口点,默认就是App。

 

3、打开主页的XAML文件,我们来完成一下UI布局。

<Page
x:Class="BackgroundAudioExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BackgroundAudioExample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Margin="28">
<TextBlock Margin="2,1,2,7" TextWrapping="Wrap">
<Span FontSize="24" FontWeight="Bold">实现后台播放,应该要具备以下条件:</Span>
<LineBreak/>
<Run FontSize="20">在清单文件中,加入后台任务的声明</Run><LineBreak/>
<Run FontSize="20">你的PC或笔记本的键盘最好具有多媒体控制键,这样方便操作</Run>
<LineBreak/>
<Run FontSize="20" Foreground="Blue">MediaElement的AudioCategory属性设置为BackgroundCapableMedia或Communications</Run>
<LineBreak/>
<Run FontSize="20">注册MediaControl的控制事件</Run>
</TextBlock>
<StackPanel Orientation="Horizontal" Margin="3,4,3,0">
<Button Content="选择音频文件" Click="onSelectFile"/>
<Button x:Name="btnPlayorPause" Content="播放" Click="onPlayOrPause" Margin="12,0,0,0"/>
<Button Content="停止" Click="onStop" Margin="8,0,0,0"/>
<TextBlock x:Name="tbMessage" Margin="30,0,0,0"/>
</StackPanel>
</StackPanel>
<MediaElement x:Name="myMediaElement" Width="0" Height="0" Opacity="0" AudioCategory="BackgroundCapableMedia" AutoPlay="False"
CurrentStateChanged="myMediaElement_CurrentStateChanged_1"
MediaFailed="myMediaElement_MediaFailed_1"
MediaEnded="myMediaElement_MediaEnded_1"
MediaOpened="myMediaElement_MediaOpened_1"/>
</Grid>
</Page>

 

4、切换代码视图,上面有几个事件要处理。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// 引入以下命名空间
using Windows.Media;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
namespace BackgroundAudioExample
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private string MusicTitle = string.Empty;//音乐标题
private string MusicArtist = string.Empty;//演唱者
private void myMediaElement_CurrentStateChanged_1(object sender, RoutedEventArgs e)
{
switch (this.myMediaElement.CurrentState)
{
case MediaElementState.Buffering:
tbMessage.Text = "加载中。";
break;
case MediaElementState.Closed:
tbMessage.Text = "已关闭。";
MediaControl.IsPlaying = false;
break;
case MediaElementState.Opening:
tbMessage.Text = "正在打开媒体。";
break;
case MediaElementState.Paused:
MediaControl.IsPlaying = false;
tbMessage.Text = "已暂停。";
btnPlayorPause.Content = "播放";
break;
case MediaElementState.Playing:
MediaControl.IsPlaying = true;
tbMessage.Text = "正在播放。";
btnPlayorPause.Content = "暂停";
break;
case MediaElementState.Stopped:
MediaControl.IsPlaying = false;
tbMessage.Text = "已停止";
btnPlayorPause.Content = "播放";
break;
default:
break;
}
}
private void myMediaElement_MediaFailed_1(object sender, ExceptionRoutedEventArgs e)
{
tbMessage.Text = "播放音频失败,请检查人品。";
}
private void myMediaElement_MediaEnded_1(object sender, RoutedEventArgs e)
{
// 播放完了,就解除事件绑定吧
MediaControl.PlayPressed -= MediaControl_PlayPressed;
MediaControl.PlayPauseTogglePressed -= MediaControl_PlayPauseTogglePressed;
MediaControl.PausePressed -= MediaControl_PausePressed;
MediaControl.StopPressed -= MediaControl_StopPressed;
}
private void myMediaElement_MediaOpened_1(object sender, RoutedEventArgs e)
{
// 注册播放控件事件
MediaControl.PlayPressed += MediaControl_PlayPressed;
MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
MediaControl.PausePressed += MediaControl_PausePressed;
MediaControl.StopPressed += MediaControl_StopPressed;
// 显示歌曲标题和歌手名字
MediaControl.TrackName = this.MusicTitle;
MediaControl.ArtistName = this.MusicArtist;
}
async void MediaControl_StopPressed(object sender, object e)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.myMediaElement.Stop();
});
}
async void MediaControl_PausePressed(object sender, object e)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
this.myMediaElement.Pause();
});
}
async void MediaControl_PlayPauseTogglePressed(object sender, object e)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
onPlayOrPause(null, null);
});
}
async void MediaControl_PlayPressed(object sender, object e)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.myMediaElement.Play();
});
}
private async void onSelectFile(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".mp3");
picker.FileTypeFilter.Add(".wma");
picker.SuggestedStartLocation = PickerLocationId.MusicLibrary;
StorageFile audioFile = await picker.PickSingleFileAsync();
if (audioFile != null)
{
// 获取音频文件的属性
var musickProperty = await audioFile.Properties.GetMusicPropertiesAsync();
this.MusicTitle = musickProperty.Title;
if (!string.IsNullOrEmpty(musickProperty.AlbumArtist))
{
this.MusicArtist = musickProperty.AlbumArtist;
}
else
{
this.MusicArtist = musickProperty.Artist;
}
// 设置播放源
var stream = await audioFile.OpenAsync(FileAccessMode.Read);
this.myMediaElement.SetSource(stream, audioFile.FileType);
}
}
private void onPlayOrPause(object sender, RoutedEventArgs e)
{
if (this.myMediaElement.CurrentState == MediaElementState.Playing)
{
this.myMediaElement.Pause();
}
else
{
this.myMediaElement.Play();
}
}
private void onStop(object sender, RoutedEventArgs e)
{
this.myMediaElement.Stop();
}
}
}



代码我们稍候再总结,现在我们迫不及待地想看一下,实验是否成功。果断运行吧。

在你的电脑上随便选一个MP3文件,然后点击播放,然后切换到“开始”屏幕,看看音乐是不是继续播放?如果是,那么实验就成功了。

 

如果你的笔记本键盘有多媒体控制键,在任务屏幕,按下“音量”控制键,就会在屏幕上看到如下图的控制按钮。

 

好了,后台播放大体情况就这样。

大家不妨测试一下,在本例中,如果你只是把MediaElement的AudioCategory属性设置为BackgroundCapableMedia,而不注册MediaControl类的事件处理,你会发现,是不能在后台播放的。

MediaControl类位于Windows.Media命名空间,要完成音频的后台播放和控制,少不了这个类。它是一个static类,所以你能想到它的所有成员都是静态的,它有N多个事件,如下面截图所示,大家不妨打开“对象浏览器”研究一下。

 

在我们本次实验中,只注册了4个事件,也是最基本的4个,大家可以试一下,注释掉其中一个,都不能后台播放,所以,这4个事件是必须的,其他的是可选。

比较好一个处理方案是在有MediaElement的页面的Loaded事件中注册这些事件处理,在UnLoaded中释放。不过本例有所不同,本例是在媒体打开时注册,媒体关闭时释放,因为本例只播放一个音频。所以没有“上一首”,“下一首”。

 

 

 

这篇关于新时尚Windows8开发(26):后台播放Musics的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/827805

相关文章

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

使用Go语言开发一个命令行文件管理工具

《使用Go语言开发一个命令行文件管理工具》这篇文章主要为大家详细介绍了如何使用Go语言开发一款命令行文件管理工具,支持批量重命名,删除,创建,移动文件,需要的小伙伴可以了解下... 目录一、工具功能一览二、核心代码解析1. 主程序结构2. 批量重命名3. 批量删除4. 创建文件/目录5. 批量移动三、如何安

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Python实现多路视频多窗口播放功能

《Python实现多路视频多窗口播放功能》这篇文章主要为大家详细介绍了Python实现多路视频多窗口播放功能的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下... 目录一、python实现多路视频播放功能二、代码实现三、打包代码实现总结一、python实现多路视频播放功能服务端开

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服