从 1607 (14393)版本开始,MediaPlayer 类就可以在前台与后台之间无缝播放,你不必再考虑前台与后之间的通信,所以从 14393 开始,你就不需要再用 BackgroundMediaPlayer 类了。无论多媒体资源是前台还是后台播放,都由 MediaPlayer 类负责。与此同时,在 XAML 控件体系中,MediaElement 类也由 MediaPlayerElement 类替代。

这些内容老周就不多说了,因为 SDK 文档的更新日志上都有说明。不管是音频或是视频都统一到 MediaPlayer 类中,正因为如此,实现后台播放视频就显得很是 Easy 了。

不废话,下面咱们来个示例来说明说明。

这个示例简单,老周就不用 Page 了,UI 的根直接来个 Grid 吧。

<Grid
x:Class="App32.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App32"> <Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition />
</Grid.RowDefinitions> <Button Content="打开视频文件" Margin="10,15" Click="OnOpen"/>
<MediaPlayerElement Name="me" Grid.Row="1" Margin="8"/> </Grid>

由于这不是项目默认生成的 Page ,所以注意(看好上面的 x:Class ,它指向对应的类),与它对应的代码文件中的类必须继承 Grid 类,不是 Page 类,代码类的基类就得与 XAML 文档的根元素匹配。

    partial class MainView : Grid
{
public MainView()
{
InitializeComponent();
}
}

如果,你觉得有必要密封这个类(不让别人继承财产),就这样修饰。

    sealed partial class MainView : Grid
{
public MainView()
{
InitializeComponent();
}
}

按钮是干啥用的呢,这样,咱们待会儿运行后,点击按钮来打开一个视频文件,然后在 MediaPlayerElement 控件中播放(显示)。

        private async void OnOpen(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".mp4");
picker.FileTypeFilter.Add(".mkv");
picker.FileTypeFilter.Add(".wmv"); StorageFile file = await picker.PickSingleFileAsync();
if (file == null) return; MediaSource source = MediaSource.CreateFromStorageFile(file);
me.Source = source;
// 开始播放
me.MediaPlayer.Play();
}

在文首老周说过,现在 UWP 应用的多媒体播放都统一由 MediaPlayer 大哥负责,因此,MediaPlayerElement 类会公开一个 MediaPlayer 属性,你可以从这个属性获取到关联的 MediaPlayer 类实例(这个类位于 Windows.Media.Playback 命名空间)。

因此你看到了,在上面最后的代码上,老周调用的 Play 方法是 MediaPlayer 类的,实际上视频是在 MediaPlayer 上管理的。MediaPlayerElement 只负责显示(或者 UI 操作,如暂停等)。

行了,代码这么搞就OK了,不过要想让应用能在后台继续播放,清单文件上的配置是少不了的。打开清单文件(默认是以清单设计器打开),切换到“功能”选项卡,勾选“背景媒体播放”。这是翻译问题,其实应该叫“后台媒体播放”才对,不管它,知道是啥意思就行了,别纠结这些无关紧要的事情。

清单文件其实是 XML 文档,所以,如果你觉得直接点两下鼠标没法装逼的话,可以手动写的。

首先,你要引入一个 v3 版本的 UWP 专用命名空间。

xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"

然后,你才能进行声明,写到 Package / Capabilities 节点下面。

  <Capabilities>
<Capability Name="internetClient" />
<uap3:Capability Name="backgroundMediaPlayback" />
</Capabilities>

最后,保存一下文件就完事了。

现在运行,随便找个视频播放,然后把程序最小化,或切换到其他应用,然后再切换回去,你会发现,当程序进入后台后,视频仍然在播放。

其实,上面的实现还不够完善。你想啊,应用移到后台,UI 是看不见的,成了多余的货了,所以,我们妨考虑,在应用扔到后台时销毁 UI,等应用回到前台时再创建 UI。当然了,我们这个例子,界面比较简单,内存占用基本看不出来区别,大约也就是 0.1 MB 的差异。不过为了演示,我们还是处理一下应用程序的这两个事件:

        public App()
{
this.InitializeComponent();
EnteredBackground += App_EnteredBackground;
LeavingBackground +=
App_LeavingBackground;
}

当应用发送到后台,会引发 EnteredBackground 事件,当应用回到前台,则发生 LeavingBackground 事件。

下面我们处理一下。

        private void App_LeavingBackground(object sender, LeavingBackgroundEventArgs e)
{
if(Window.Current.Content == null) //这里为什么要判断 null 不 null 呢?
{
CreateUI(); //重建界面
}
} private void App_EnteredBackground(object sender, EnteredBackgroundEventArgs e)
{
Window.Current.Content = null;//取消对 UI 实例的引用
GC.Collect(); //打扫卫生
}

进入后台后,把当前窗口的内容设为 null,可以解除对 XAML 对象的引用,然后扛一根大扫把来,调用GC成员打扫一下,清理内存。

当重新回到前台时,重建界面,这里为啥我要先看看窗口的内容是否为 null 呢?很简单啊,如果不为 null 说明界面创建好了,那就不必要重复创建了,没意义了。为啥会这样,因为有件事你得知道,当启动应用时,会执行 OnLaunched 方法,这个没疑问吧。然后呢,LeavingBackground 事件会发生一次。而我们在很多时候,OnLaunched 方法中已经建好界面了,正因为如此,在处理 LeavingBackground 事件时,一定要判断一下界面是否创建过了,如果已有界面实例,就不必再创建了。

顺便补一下,CreateUI 方法代码如下。

        void CreateUI()
{
MainView mv = Window.Current.Content as MainView;
if (mv == null)
mv = new MainView();
Window.Current.Content = mv;
}

然后在你运行实例后,又出现新问题了。还记得吧?我们在 XAML 中放了一个 MediaPlayerElement 控件,现在应用进入后台后界面会释放,所以 MediaPlayerElement 控件的实例也会被干掉,等到应用再回到前台,MediaPlayerElement 控件已经是新创建的实例了,不是刚才的那个实例了,这就造成:回到应用后,视频不再播放了

要解决这问题,我们只要想办法让 MediaPlayer 实例的生命周期与应用同步就好了,对,把它变成静态变量(static)。所以,我写了这么个类。

    class MediaPlayerHelper
{
static MediaPlayer _player; public static MediaPlayer CurrentPlayer
{
get
{
if (_player == null)
_player = new MediaPlayer();
return
_player;
}
}
}

这样就可以让它静态了,别忘了,如果 MediaPlayerElement 控件实例是新创建的,会关联地创建一个 MediaPlayer 实例。为了让每个新创建的 MediaPlayerElement 控件实例所关联的 MediaPlayer 实例相同,我们可以调用控件的 SetMediaPlayer 方法。

回到咱们前面那个 Grid 的子类代码中,在构造函数中加上这么一句:

        public MainView()
{
InitializeComponent();
me.SetMediaPlayer(MediaPlayerHelper.CurrentPlayer);
}

这样一来,不管咱们在应用生命周期内创建了多少个 MediaPlayerElement 控件实例,其关联的 MediaPlayer 对象都是我们上面公开的那个 CurrentPlayer 了,这确保了 MediaPlayer 实例的全局唯一性。

现在再次运行示例,在界面元素销毁后再次回到应用程序,视频仍能继续播放。

好了,今天的话题聊完了,该用饭了。

【Win 10 应用开发】在后台播放视频的更多相关文章

  1. 【Win 10 应用开发】Toast通知激活应用——前台&后台

    老周最近热衷于讲故事,接下来还是讲故事时间. 有人问我:你上大学的时候,有加入过学生会吗?读大学有没有必要加入学生会? 哎哟,这怎么回答呢,从短期来说,加入学生会有点用,至少可以娱乐一下,运气好的话, ...

  2. 【Win 10应用开发】延迟共享

    延迟共享是啥呢,这么说吧,就是在应用程序打开共享面板选择共享目标时,不会设置要共享的数据,而是等到共享目标请求数据时,才会发送数据,而且,延迟操作可以在后台进行. 这样说似乎过于抽象,最好的诠释方法, ...

  3. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  4. 【Win 10 应用开发】导入.pfx证书

    这个功能其实并不常用,一般开发较少涉及到证书,不过,简单了解一下还是有必要的. 先来说说制作测试证书的方法,这里老周讲两种方法,可以生成用于测试的.pfx文件. 产生证书,大家都知道有个makecer ...

  5. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...

  6. 【Win 10 应用开发】RTM版的UAP项目解剖

    Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家 ...

  7. 【Win 10应用开发】认识一下UAP项目

    Windows 10 SDK预览版需要10030以上版本号的Win 10预览版系统才能使用.之前我安装的9926的系统,然后安装VS 2015 CTP 6,再装Win 10 SDK,但是在新建项目后, ...

  8. 【Win 10 应用开发】在代码中加载文本资源

    记得前一次,老周给大伙,不,小伙伴们介绍了如何填写 .resw 文件,并且在 XAML 中使用 x:Uid 标记来加载.也顺便给大伙儿分析了运行时是如何解析 .resw 文件的. 本来说好了,后续老周 ...

  9. 在iOS开发中如何播放视频

     技术博客http://www.cnblogs.com/ChenYilong/  新浪微博http://weibo.com/luohanchenyilong  如何播放视频 •iOS提供了叫做MPMo ...

随机推荐

  1. Java boolean类型

    有关java boolean类型的定义: The boolean data type has only two possible values: true and false. Use this da ...

  2. ELK系列~对fluentd参数的理解

    这段时候一直在研究ELK框架,主要集成在对fluentd和nxlog的研究上,国内文章不多,主要看了一下官方的API,配合自己的理解,总结了一下,希望可以帮到刚入行的朋友们! Fluentd(日志收集 ...

  3. swift之函数式编程(三)

    文章来源于<Functional Programing in Swift>,本系列仅仅是观后概括的一些内容 Wrapping Core Image 上一篇文章我们介绍了 高阶函数并且展示了 ...

  4. Element ui表格展示图片问题

    当需要遍历图片时,不能直接使用prop绑定值,具体 代码如下 <el-table-column label="头像" width="100"> &l ...

  5. poj 2345 Central heating

    Central heating Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 678   Accepted: 310 Des ...

  6. Hive简单安装

    数据库的创建 Hive1版本 在此之前要安装好JDK,HADOOP,下载解压Hive 在root下安装mysql:yum install mysql-server mysql-client //一般M ...

  7. 【开源】【前后端分离】【优雅编码】分享我工作中的一款MVC+EF+IoC+Layui前后端分离的框架——【NO.1】框架概述

    写博客之前总想说点什么,但写的时候又忘了想说点什么,算了,不说了,还是来送福利吧. 今天是来分享我在平时工作中搭建的一套前后端分离的框架. 平时工作大多时候都是在做管理类型的软件开发,无非就是增.删. ...

  8. 用git上传本地文件到github

    1.在自己的github账号下新建仓库--------得到github仓库地址 2.本地安装git---在将要克隆的文件夹下 右击点击Git Bash Here 3.输入命令 $ git clone ...

  9. 一场围绕着‘Deeping Learning’的高考

    Deep Learning的基本思想和方法 实际生活中,人们为了解决一个问题,如对象的分类(对象可是是文档.图像等),首先必须做的事情是如何来表达一个对象,即必须抽取一些特征来表示一个对象,如文本的处 ...

  10. C#之可选参数和命名参数

    设计方法的参数是,可以将部分参数和全部参数分配默认值,然后调用这些方法的时候可以选择不提供部分实参,使用参数定义的默认值,另外,还可以在调用方法的时候通过指定参数名称来传递实参. 例如: public ...