與眾不同 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
[源碼下載]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM