zoukankan      html  css  js  c++  java
  • 与众不同 windows phone (15) Media(媒体)之后台播放音频

    [索引页]
    [源码下载]


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



    作者:webabcd


    介绍
    与众不同 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
    [源码下载]

  • 相关阅读:
    Beta冲刺<7/10>
    Beta冲刺<6/10>
    Beta冲刺<5/10>
    Beta冲刺--冲刺总结
    Beta冲刺<4/10>
    实验四
    结对编程第二阶段
    实验二 结对编程第一阶段
    实验报告
    团队作业第六次——Beta冲刺
  • 原文地址:https://www.cnblogs.com/webabcd/p/2604457.html
Copyright © 2011-2022 走看看