用uwp自带的控件实现一个极简的媒体播放器

1. 前言

    根据上级要求,使用uwp控件构建一个现有的媒体播放器,一开始听说这个要求我都蒙了,我第一感觉这个东西特别难写,应该涉及到一些视频格式解析的问题,详情看前bilibili员工dalao的项目:https://github.com/Bilibili/flv.js(可惜B站只给这个大佬开5000左右的工资把人家给逼走了

    我觉得非常绝望,准备自杀了是,但是后来查了文档之后发现,其实人家都帮我们写好了ORZ,然后就没什么好说的了,做一个API调用者我觉得挺好=_=b

2. 预览

    




3. 代码分析

    github地址

    先看一下Mainpage.xaml

<Page
    x:Class="MediaPlayerDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MediaPlayerDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <TextBlock Name="State" Grid.Column="1" Grid.Row="0"/>

        
      <Button 
          Name="OpenBtn"
          HorizontalAlignment="Center"
          Content="Open the media file" 
          Grid.Row="1" Grid.Column="1" 
          Click="ButtonClickHandler"
      />

<MediaPlayerElement Name="MediaPlayer" AutoPlay="False" Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="3" Visibility="Collapsed" AreTransportControlsEnabled="True" /> </Grid></Page>

    这是这个项目主页面的配置文件看的出来,这个页面就只有三个控件,一个用来表示打开文件状态的textblock,一个用来播放媒体文件的主控件,还有一个选择文件的按钮

<Button 
          Name="OpenBtn"
          HorizontalAlignment="Center"
          Content="Open the media file" 
          Grid.Row="1" Grid.Column="1" 
          Click="ButtonClickHandler"
      />

    其中,这个Click="ButtonClickHandler"是一个通向后端的一个接口,向后端一个名字为ButtonClickHandler的函数传递一个事件,用来触发接下来的函数。

       而真正的主体,也就是我们的媒体播放器,在默认的情况下是隐藏的。

        

<MediaPlayerElement 
            Name="MediaPlayer" AutoPlay="False"
            Grid.Row="0" Grid.Column="0"
            Grid.RowSpan="3" Grid.ColumnSpan="3"
            Visibility="Collapsed"
            AreTransportControlsEnabled="True"
        />

        其中,Visibility属性代表的是当前控件的显示状态,默认是Collapsed的,当我们使用OpenBtn的时候,触发后端的task函数,使之显示出来。

    大致讲完了前端,我们看一下后端的C#代码:

    

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.Core;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Core;
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;

// https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x804 上介绍了“空白页”项模板

namespace MediaPlayerDemo
{
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async System.Threading.Tasks.Task openMediaFile()
        {
            FileOpenPicker fileOpenPicker = new FileOpenPicker();
            fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
            fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            fileOpenPicker.FileTypeFilter.Add(".mp3");
            fileOpenPicker.FileTypeFilter.Add(".mp4");

            StorageFile file = await fileOpenPicker.PickSingleFileAsync();
            if (file != null)
            {
                // Application now has read/write access to the picked file
                MediaPlayer.Source = MediaSource.CreateFromStorageFile(file);
                MediaPlayer.Visibility = Visibility.Visible;
                OpenBtn.Visibility = Visibility.Collapsed;

                MediaPlayer.MediaPlayer.MediaEnded += new TypedEventHandler<Windows.Media.Playback.MediaPlayer, object>((player, resource) => {
                    OpenBtn.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
                        OpenBtn.Visibility = Visibility.Visible;
                        MediaPlayer.Visibility = Visibility.Collapsed;
                    });
                });

            }
            else
            {
                State.Text = "unable to open the file!";
            }
        }

        // action listener and handle the event
        private void ButtonClickHandler(object sender, RoutedEventArgs e) 
        {
            openMediaFile();
        }
    }
}

      很简单的代码,其实我什么都没有做,仅仅只是调用了一下Windows自带的API,我们来看一下点击了OpenBtn之后发生了什么,首先,前端向后端发送了一个请求(object类型),并触发了一个事件,这个时候下列函数被调用:

         // action listener and handle the event
        private void ButtonClickHandler(object sender, RoutedEventArgs e) 
        {
            openMediaFile();
        }

       这个代码调用了openMediaFile函数,那么openMediaFile函数到底做了什么呢?我们来看看:

 

        private async System.Threading.Tasks.Task openMediaFile()
        {
            FileOpenPicker fileOpenPicker = new FileOpenPicker();
            fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
            fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            fileOpenPicker.FileTypeFilter.Add(".mp3");
            fileOpenPicker.FileTypeFilter.Add(".mp4");

            StorageFile file = await fileOpenPicker.PickSingleFileAsync();
            if (file != null)
            {
                // Application now has read/write access to the picked file
                MediaPlayer.Source = MediaSource.CreateFromStorageFile(file);
                MediaPlayer.Visibility = Visibility.Visible;
                OpenBtn.Visibility = Visibility.Collapsed;

                MediaPlayer.MediaPlayer.MediaEnded += new TypedEventHandler<Windows.Media.Playback.MediaPlayer, object>((player, resource) => {
                    OpenBtn.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
                        OpenBtn.Visibility = Visibility.Visible;
                        MediaPlayer.Visibility = Visibility.Collapsed;
                    });
                });

            }
            else
            {
                State.Text = "unable to open the file!";
            }
        }

        首先需要解决的问题是,文件的来源,我怎么从磁盘中选择一个合适的文件读取到媒体播放器中呢

            FileOpenPicker fileOpenPicker = new FileOpenPicker();
            fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
            fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            fileOpenPicker.FileTypeFilter.Add(".mp3");
            fileOpenPicker.FileTypeFilter.Add(".mp4");

            StorageFile file = await fileOpenPicker.PickSingleFileAsync();

  前面的五行初始化了一个文件选择视图,第二到第五行初始化了这个选择器,指定了选择文件的后缀格式,指派了选择器风格,  最后一行是神来之笔,file是文件对象,能够等到用户选择完毕之后再初始化。

            if (file != null)
            {
                // Application now has read/write access to the picked file
                MediaPlayer.Source = MediaSource.CreateFromStorageFile(file);
                MediaPlayer.Visibility = Visibility.Visible;
                OpenBtn.Visibility = Visibility.Collapsed;

                MediaPlayer.MediaPlayer.MediaEnded += new TypedEventHandler<Windows.Media.Playback.MediaPlayer, object>((player, resource) => {
                    OpenBtn.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
                        OpenBtn.Visibility = Visibility.Visible;
                        MediaPlayer.Visibility = Visibility.Collapsed;
                    });
                });

            }
            else
            {
                State.Text = "unable to open the file!";
            }

当file对象被初始化之后task函数会检查file是否被成功打开,如果file对象存在,那么设置媒体播放器的播放源为file,将前端的媒体播放器设置为可见,并且将选择文件的按钮隐藏起来,并且监听一个播放结束的事件,当媒体文件播放结束之后,重新显示选择文件的按钮,隐藏媒体播放器。


至此,整块的代码就分析完毕了

4. 引用来源(抄了很多代码,很惭愧

// 实现fileOpenPicker的Demo

https://docs.microsoft.com/zh-cn/uwp/api/windows.storage.pickers.fileopenpicker#examples

// 监听媒体播放结束事件的Demo

https://docs.microsoft.com/zh-cn/uwp/api/windows.ui.xaml.controls.mediaplayerelement#handle-media-events

// C# 事件(Event)

http://www.runoob.com/csharp/csharp-event.html

// UI线程相关

http://edi.wang/post/2016/2/18/windows-10-uwp-async-await-ui-thread

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值