与众不同 windows phone (15) - Media(媒体)之后台播放音频

介绍 与众不同 windows phone 7.5 (sdk 7.1) 之媒体

  • 通过 AudioPlayerAgent 实现在后台播放音频

示例 演示如何通过后台代理的方式来实现音频在后台的播放 1、后台代理 MyAudioPlayerAgent/AudioPlayer.cs

复制代码
/*

 * 本例演示如何播放后台音频(以 AudioPlayerAgent 为例,另 AudioStreamingAgent 用于流式播放音频)

 * 建议使用 AudioPlaybackAgent 类型的模板创建此项目

 * 

 * BackgroundAgent - 后台代理类,抽象类,它是 ScheduledTaskAgent、AudioPlayerAgent 和 AudioStreamingAgent 的基类

 *     NotifyComplete() - 用于通知系统,代理已经完成了当前的任务,调用此方法后,系统才会去准备执行下一次任务

 *     Abort() - 用于通知系统,放弃此次和以后的任务

 *     OnCancel() - 后台代理被取消时所执行的方法(由系统调用,比如后台代理转到休眠状态或终止状态前会调用此方法)

 *     

 * AudioPlayerAgent - 后台播放音频的代理类

 *     OnError() - 当播放中出现错误时,系统会调用此方法

 *     OnPlayStateChanged() - 当播放状态发生改变时,系统会调用此方法(错误状态除外)

 *     OnUserAction() - 当程序改变播放行为时,系统会调用此方法

 *     

 * PlayState - Microsoft.Phone.BackgroundAudio.PlayState 枚举

 *     Unknown, Stopped, Paused, Playing, BufferingStarted, BufferingStopped, TrackReady, TrackEnded, Rewinding, FastForwarding, Shutdown, Error

 *     

 * UserAction - Microsoft.Phone.BackgroundAudio.UserAction 枚举

 *     Stop, Pause, Play, SkipNext, SkipPrevious, FastForward, Rewind, Seek

 *     

 * AudioTrack - 音频对象

 *     Source - 音频的地址,远程地址或独立存储地址均可

 *     Title - 音频名称

 *     Duration - 音频时长

 *     Album - 专辑名称

 *     AlbumArt - 专辑封面的 Uri 地址,远程地址或独立存储地址均可,如果使用独立存储地址则其目录必须是 Shared/Media

 *     Artist - 艺术家

 *     PlayerControls - 锁屏等状态下的播放器控件显示(Microsoft.Phone.BackgroundAudio.EnabledPlayerControls 枚举)

 *         None = 0, SkipNext = 1, SkipPrevious = 2, FastForward = 4, Rewind = 8, Pause = 16, All = 31

 *     Tag - 任意内容,即为 AudioTrack 绑定一个上下文数据

 *     BeginEdit() - 将 AudioTrack 设置为编辑状态(如果需要修改 AudioTrack 的属性则需要将 AudioTrack 设置为编辑状态)

 *     EndEdit() - 结束 AudioTrack 的编辑状态

 */



using System;

using System.Windows;

using Microsoft.Phone.BackgroundAudio;



using System.Collections.Generic;



namespace MyAudioPlayerAgent

{

    public class AudioPlayer : AudioPlayerAgent

    {

        // 播放列表

        private static List<AudioTrack> _playList = new List<AudioTrack>

        {

            new AudioTrack(new Uri("SuperMario.mp3", UriKind.Relative), "title", "artist", "album", null, null, EnabledPlayerControls.Pause),

            new AudioTrack(new Uri("http://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute), "标题", "艺术家", "专辑", null, null, EnabledPlayerControls.All)

        };



        // 当前播放的 Track 在整个播放列表中的位置

        private static int _currentTrackNumber = 0;



        /*

         * _classInitialized - 用于标记 AudioPlayer 是否已经被初始化

         *     标记成 volatile 是为了避免编译器认为此字段无外部修改,而将其优化放入寄存器(标记成 volatile 的字段只会放在内存中)

         *     一般来说,多任务环境下各任务间共享的字段应该被标记为 volatile

         */

        private static volatile bool _classInitialized;



        public AudioPlayer()

        {

            if (!_classInitialized)

            {

                _classInitialized = true;

                Deployment.Current.Dispatcher.BeginInvoke(delegate

                {

                    Application.Current.UnhandledException += AudioPlayer_UnhandledException;

                });

            }

        }



        private void AudioPlayer_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)

        {

            if (System.Diagnostics.Debugger.IsAttached)

            {

                System.Diagnostics.Debugger.Break();

            }

        }



        // 播放状态发生改变时所调用的方法

        protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)

        {

            switch (playState)

            {

                case PlayState.TrackReady:

                    player.Play();

                    break;

                case PlayState.TrackEnded:

                    PlayNextTrack(player);

                    break;

                case PlayState.Playing:

                    break;

                case PlayState.Paused:

                    break;

                case PlayState.Stopped:

                    break;

                case PlayState.BufferingStarted:

                    break;

                case PlayState.BufferingStopped:

                    break;

                case PlayState.Rewinding:

                    break;

                case PlayState.FastForwarding:

                    break;

                case PlayState.Shutdown:

                    break;

                case PlayState.Unknown:

                    break;

            }



            NotifyComplete();

        }



        // 当程序改变播放行为时所调用的方法

        protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)

        {

            switch (action)

            {

                case UserAction.Play:

                    PlayTrack(player);

                    break;

                case UserAction.SkipPrevious:

                    PlayPreviousTrack(player);

                    break;

                case UserAction.SkipNext:

                    PlayNextTrack(player);

                    break;

                case UserAction.Rewind:

                    player.Rewind();

                    break;

                case UserAction.FastForward:

                    player.FastForward();

                    break;

                case UserAction.Seek:

                    player.Position = (TimeSpan)param;

                    break;

                case UserAction.Pause:

                    player.Pause();

                    break;

                case UserAction.Stop:

                    player.Stop();

                    break;

            }



            NotifyComplete();

        }



        // 播放下一个 Track

        private void PlayNextTrack(BackgroundAudioPlayer player)

        {

            if (++_currentTrackNumber >= _playList.Count)

                _currentTrackNumber = 0;



            PlayTrack(player);

        }



        // 播放上一个 Track

        private void PlayPreviousTrack(BackgroundAudioPlayer player)

        {

            if (--_currentTrackNumber < 0)

                _currentTrackNumber = _playList.Count - 1;



            PlayTrack(player);

        }



        // 播放当前 Track

        private void PlayTrack(BackgroundAudioPlayer player)

        {

            player.Track = _playList[_currentTrackNumber];

        }



        // 出现异常时所调用的方法

        protected override void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal)

        {

            if (isFatal)

                Abort();

            else

                NotifyComplete();

        }



        // 当后台代理转到休眠状态或终止状态前,系统会自动调用此方法,需要在 5 秒内执行完毕

        protected override void OnCancel()

        {



        }

    }

}



/*

 * 主程序引用此项目后,会在 manifest 中添加如下信息:

 * <ExtendedTask Name="BackgroundTask">

 * <BackgroundServiceAgent Specifier="AudioPlayerAgent" Name="MyAudioPlayerAgent" Source="MyAudioPlayerAgent" Type="MyAudioPlayerAgent.AudioPlayer" />

 * </ExtendedTask>

 */
复制代码

2、前台调用后台代理播放音频 BackgroundAudio.xaml

复制代码
<phone:PhoneApplicationPage 

    x:Class="Demo.Media.BackgroundAudio"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="Portrait" Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">



    <Grid x:Name="LayoutRoot" Background="Transparent">

        

        <StackPanel Orientation="Vertical">

            <Button x:Name="btnPrev" Content="上一首" Click="btnPrev_Click" />

            <Button x:Name="btnRewind" Content="快退" Click="btnRewind_Click" />

            <Button x:Name="btnPlay" Content="播放" Click="btnPlay_Click" />

            <Button x:Name="btnFastForward" Content="快进" Click="btnFastForward_Click" />

            <Button x:Name="btnNext" Content="下一首" Click="btnNext_Click" />



            <TextBlock x:Name="lblCurrentTrack" />

            <TextBlock x:Name="lblPosition" />

        </StackPanel>

                

    </Grid>

 

</phone:PhoneApplicationPage>
复制代码

BackgroundAudio.xaml.cs

复制代码
/*

 * 本例演示如何播放后台音频

 * 

 * BackgroundAudioPlayer - 提供调用后台播放音频的相关功能

 *     Instance - 返回 BackgroundAudioPlayer 实例

 *     Track - 当前的 AudioTrack 对象。说明参见:MyAudioPlayerAgent/AudioPlayer.cs

 *     PlayerState - 播放器状态(Microsoft.Phone.BackgroundAudio.PlayState 枚举)。说明参见:MyAudioPlayerAgent/AudioPlayer.cs

 *     Position - 当前 AudioTrack 的播放位置

 *     CanPause - 是否可暂停

 *     CanSeek - 是否可以设置 Position 属性

 *     BufferingProgress - 缓冲百分比(0 - 1之间)

 *     Volume - 音量(0 - 1之间,默认值为 0.85)。注:目前 wp 没有提供 uvc(Universal Volume Control) 的接口

 *     

 *     Play - 播放当前 AudioTrack 的当前位置

 *     Pause - 暂停

 *     Stop - 停止

 *     Rewind - 快退

 *     FastForward - 快进 

 *     SkipPrevious - 跳至上一个音频

 *     SkipNext - 跳至下一个音频

 *     Close - 关闭并释放所有资源

 *     

 *     PlayStateChanged - PlayState 发生改变时所触发的事件

 */



using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using Microsoft.Phone.Controls;



using Microsoft.Phone.BackgroundAudio;

using System.Windows.Navigation;

using System.IO.IsolatedStorage;

using System.Windows.Resources;



namespace Demo.Media

{

    public partial class BackgroundAudio : PhoneApplicationPage

    {

        public BackgroundAudio()

        {

            InitializeComponent();



            Init();

        }



        protected override void OnNavigatedTo(NavigationEventArgs e)

        {

            ProcessPlayState();

        }



        private void Init()

        {

            // 由于播放本地音频时只能从独立存储中播放,所以此处把示例用音频文件从程序包中复制到独立存储

            using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())

            {

                if (!storage.FileExists("SuperMario.mp3"))

                {

                    StreamResourceInfo resource = Application.GetResourceStream(new Uri("Assets/SuperMario.mp3", UriKind.Relative));



                    using (IsolatedStorageFileStream file = storage.CreateFile("SuperMario.mp3"))

                    {

                        int chunkSize = 4096;

                        byte[] bytes = new byte[chunkSize];

                        int byteCount;



                        while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0)

                        {

                            file.Write(bytes, 0, byteCount);

                        }

                    }

                }

            }



            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);



            BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);

        }



        // 实时更新当前音频播放的位置

        void CompositionTarget_Rendering(object sender, EventArgs e)

        {

            if (BackgroundAudioPlayer.Instance != null)

                lblPosition.Text = BackgroundAudioPlayer.Instance.Position.TotalSeconds.ToString();

        }



        void Instance_PlayStateChanged(object sender, EventArgs e)

        {

            ProcessPlayState();

        }



        void ProcessPlayState()

        {

            // 指定播放按钮是显示“播放”还是“暂停”

            switch (BackgroundAudioPlayer.Instance.PlayerState)

            {

                case PlayState.Playing:

                    btnPlay.Content = "暂停";

                    break;



                case PlayState.Paused:

                case PlayState.Stopped:

                    btnPlay.Content = "播放";

                    break;

            }



            // 显示音频的 Title 和 Artist

            if (BackgroundAudioPlayer.Instance.Track != null)



                lblCurrentTrack.Text = BackgroundAudioPlayer.Instance.Track.Title + " by " + BackgroundAudioPlayer.Instance.Track.Artist;

        }



        // 播放或暂停音频

        private void btnPlay_Click(object sender, RoutedEventArgs e)

        {

            if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)

            {

                BackgroundAudioPlayer.Instance.Pause();

            }

            else

            {

                BackgroundAudioPlayer.Instance.Play();

            }

        }



        // 跳至下一首音频

        private void btnNext_Click(object sender, RoutedEventArgs e)

        {

            BackgroundAudioPlayer.Instance.SkipNext();

        }



        // 跳至上一首音频

        private void btnPrev_Click(object sender, RoutedEventArgs e)

        {

            BackgroundAudioPlayer.Instance.SkipPrevious();

        }



        // 快退

        private void btnRewind_Click(object sender, RoutedEventArgs e)

        {

            if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)

                BackgroundAudioPlayer.Instance.Rewind();

        }



        // 快进

        private void btnFastForward_Click(object sender, RoutedEventArgs e)

        {

            if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)

                BackgroundAudioPlayer.Instance.FastForward();

        }

    }

}
复制代码

OK [源码下载]

你可能感兴趣的:(windows phone)