none
程序在调用windowPhone音频播放代理是,报错 RRS feed

  • 问题

  • 由于是刚学WP开发,有些问题,描述不清,大概就是:

    创建了一个WindowPhone音乐播放代理项目,然后在WindowPhone应用程序中调用,进行音乐播放,结果报

    system.InvalidOperationException的错误,无法打断点调试,也不知道出错原因。

    我把代码放到下面,希望谁能帮我解决下:

    音乐播放代理:

    namespace MyAudioPlaybackAgent
    {
        public class AudioPlayer : AudioPlayerAgent
        {
            // 添加实例曲目
            private static AudioTrack m_MyTrack = new AudioTrack(new Uri("xxzj.mp3", UriKind.Relative), "相信自己", null, null, null);
            //*********************************************************************************************************//
            private static volatile bool _classInitialized;
    
    
            /// <remarks>
            /// AudioPlayer 实例可共享同一进程。
            /// 静态字段可用于 AudioPlayer 实例之间共享状态
            /// 或与音频流代理通信。
            /// </remarks>
            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)
                { 
                    // 出现为处理的一场强行进入调试器
                    Debugger.Break();
                }
            }
           
    
            /// <summary>
            /// playstate 更改时调用,但 Error 状态除外(参见 OnError)
            /// </summary>
            /// <param name="player">BackgroundAudioPlayer</param>
            /// <param name="track">在 playstate 更改时播放的曲目</param>
            /// <param name="playState">播放机的新 playstate </param>
            /// <remarks>
            /// 无法取消播放状态更改。即使应用程序
            /// 导致状态自行更改也会提出这些更改,假定应用程序已经选择了回调。
            ///
            /// 值得注意的 playstate 事件:
            /// (a) TrackEnded: 播放器没有当前曲目时激活。代理可设置下一曲目。
            /// (b) TrackReady: 音轨已设置完毕,现在可以播放。
            ///
            /// 只在代理请求完成之后调用一次 NotifyComplete(),包括异步回调。
            /// </remarks>
            protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
            {
                switch (playState)
                {
                    case PlayState.TrackEnded:
                        //player.Track = GetPreviousTrack();
    
                        // 如果播放结束,则循环,由于本实例只有一段曲目
                        player.Track = m_MyTrack;
                        break;
                    case PlayState.TrackReady:
                        player.Play();
                        break;
                    case PlayState.Shutdown:
                        // TODO: 在此处理关机状态(例如保存状态)
                        break;
                    case PlayState.Unknown:
                        break;
                    case PlayState.Stopped:
                        break;
                    case PlayState.Paused:
                        break;
                    case PlayState.Playing:
                        break;
                    case PlayState.BufferingStarted:
                        break;
                    case PlayState.BufferingStopped:
                        break;
                    case PlayState.Rewinding:
                        break;
                    case PlayState.FastForwarding:
                        break;
                }
                // 报告系统,本次任务完成
                NotifyComplete();
            }
    
            /// <summary>
            /// 在用户使用应用程序/系统提供的用户界面请求操作时调用
            /// </summary>
            /// <param name="player">BackgroundAudioPlayer</param>
            /// <param name="track">用户操作期间播放的曲目</param>
            /// <param name="action">用户请求的操作</param>
            /// <param name="param">与请求的操作相关联的数据。
            /// 在当前版本中,此参数仅适合与 Seek 操作一起使用,
            /// 以指明请求的乐曲的位置</param>
            /// <remarks>
            /// 用户操作不自动对系统状态进行任何更改;如果用户操作受支持,
            /// 以便执行用户操作(如果这些操作受支持)。
            ///
            /// 只在代理请求完成之后调用 NotifyComplete() 一次,包括异步回调。
            /// </remarks>
            protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
            {
                try
                {
                    switch (action)
                    {
                        case UserAction.Play:
                            if (player.PlayerState != PlayState.Playing)
                            {
                                player.Play();
                            }
                            break;
                        case UserAction.Stop:
                            //......
                            if (player.PlayerState != PlayState.Playing)
                            {
                                player.Stop();
                            }
    
                            break;
                        case UserAction.Pause:
                            player.Pause();
                            break;
                        case UserAction.FastForward:
                            //player.FastForward();
                            break;
                        case UserAction.Rewind:
                            //player.Rewind();
                            break;
                        case UserAction.Seek:
                            //player.Position = (TimeSpan)param;
                            break;
                        case UserAction.SkipNext:
                            //player.Track = GetNextTrack();
                            break;
                        case UserAction.SkipPrevious:
                            //AudioTrack previousTrack = GetPreviousTrack();
                            //if (previousTrack != null)
                            //{
                            //    player.Track = previousTrack;
                            //}
                            break;
                    }
                    // 通知系统
                    NotifyComplete();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);                
                }
                
               
            }
    
            /// <summary>
            /// 实现逻辑以获取下一个 AudioTrack 实例。
            /// 在播放列表中,源可以是文件、Web 请求,等等。
            /// </summary>
            /// <remarks>
            /// AudioTrack URI 确定源,源可以是:
            /// (a) 独立存储器文件(相对 URI,表示独立存储器中的路径)
            /// (b) HTTP URL(绝对 URI)
            /// (c) MediaStreamSource (null)
            /// </remarks>
            /// <returns>AudioTrack 实例,或如果播放完毕,则返回 null</returns>
            private AudioTrack GetNextTrack()
            {
                // TODO: 添加逻辑以获取下一条音轨
    
                AudioTrack track = null;
    
                // 指定曲目
    
                return track;
            }
    
            /// <summary>
            /// 实现逻辑以获取前一个 AudioTrack 实例。
            /// </summary>
            /// <remarks>
            /// AudioTrack URI 确定源,它可以是:
            /// (a) 独立存储器文件(相对 URI,表示独立存储器中的路径)
            /// (b) HTTP URL(绝对 URI)
            /// (c) MediaStreamSource (null)
            /// </remarks>
            /// <returns>AudioTrack 实例,或如果不允许前一曲目,则返回 null</returns>
            private AudioTrack GetPreviousTrack()
            {
                // TODO: 添加逻辑以获取前一条音轨
    
                AudioTrack track = null;
    
                // 指定曲目
    
                return track;
            }
    
            /// <summary>
            /// 每次播放出错(如 AudioTrack 未正确下载)时调用
            /// </summary>
            /// <param name="player">BackgroundAudioPlayer</param>
            /// <param name="track">出现错误的曲目</param>
            /// <param name="error">出现的错误</param>
            /// <param name="isFatal">如果为 true,则播放不能继续并且曲目播放将停止</param>
            /// <remarks>
            /// 不保证在所有情况下都调用此方法。例如,如果后台代理程序
            /// 本身具有未处理的异常,则不会回调它来处理它自己的错误。
            /// </remarks>
            protected override void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal)
            {
                if (isFatal)
                {
                    Abort();
                }
                else
                {
                    NotifyComplete();
                }
               // MessageBox.Show(error.Message);
    
            }
    
            /// <summary>
            /// 取消代理请求时调用
            /// </summary>
            /// <remarks>
            /// 取消请求后,代理需要 5 秒钟完成其工作,
            /// 通过调用 NotifyComplete()/Abort()。
            /// </remarks>
            protected override void OnCancel()
            {
    
            }
        }
    }

    然后是 应用程序中调用的代码:

    前台:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
                <StackPanel >
                    <StackPanel Orientation="Horizontal">
                        <Button Content="播放/暂停" x:Name="btnStart_Pruse" Click="btnStart_Pruse_Click_1"/>
                        <Button Content="停止" x:Name="btnStop" Click="btnStop_Click_1"/>
                        <Button Content="关闭" x:Name="btnClose" Click="btnClose_Click_1"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock>音量调整:</TextBlock>
                        <Slider Name="sldVl" Width="280" Maximum="1" Value="0.5" Minimum="0" SmallChange="0.01" ValueChanged="sldVl_ValueChanged_1"/>
                    </StackPanel>
                    <TextBlock Name="txtState" Text="准备就绪:"/>
                    <TextBlock Name="txtInfo" />
                </StackPanel>
            </Grid>

    后台:

     // 构造函数
            public MainPage()
            {
                InitializeComponent();
    
                // 用于本地化 ApplicationBar 的示例代码
                //BuildLocalizedApplicationBar();
    
                BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(BackgroundAudioPlayer_PlayStateChanged);
            }
    
            private void BackgroundAudioPlayer_PlayStateChanged(object sender, EventArgs e)
            {
                switch (BackgroundAudioPlayer.Instance.PlayerState)
                {
                    //case PlayState.BufferingStarted:
                    //    break;
                    //case PlayState.BufferingStopped:
                    //    break;
                    case PlayState.Error:
                        this.txtState.Text = "出错。";
                        break;
                    //case PlayState.FastForwarding:
                    //    break;
                    case PlayState.Paused:
                        this.txtState.Text = "已暂停。";
                        break;
                    case PlayState.Playing:
                        this.txtState.Text = "正在播放。";
                        if (BackgroundAudioPlayer.Instance.Track != null)
                        {
                            this.txtInfo.Text = "当前项目:" + BackgroundAudioPlayer.Instance.Track.Title;
                        }
                        break;
                    //case PlayState.Rewinding:
                    //    break;
                    case PlayState.Shutdown:
                        break;
                    case PlayState.Stopped:
                        this.txtState.Text = "已停止。";
                        break;
                    //case PlayState.TrackEnded:
                    //    break;
                    //case PlayState.TrackReady:
                    //    break;
                    //case PlayState.Unknown:
                    //    break;
                    default:
                        break;
                }
            }
    
            private void btnStart_Pruse_Click_1(object sender, RoutedEventArgs e)
            {
                if (BackgroundAudioPlayer.Instance.PlayerState != PlayState.Playing)
                {
                    BackgroundAudioPlayer.Instance.Play();
                }
                else
                {
                    BackgroundAudioPlayer.Instance.Pause();
                }
            }
    
            private void btnStop_Click_1(object sender, RoutedEventArgs e)
            {
                BackgroundAudioPlayer.Instance.Stop();
            }
    
            private void btnClose_Click_1(object sender, RoutedEventArgs e)
            {
                BackgroundAudioPlayer.Instance.Close();
                this.txtState.Text = "已关闭。";
                this.txtInfo.Text = "";
            }
    
            private void sldVl_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                BackgroundAudioPlayer.Instance.Volume = e.NewValue;
            }
    
    
            // 根据播放状态,调整UI显示
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                base.OnNavigatedTo(e);
    
                if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing)
                {
                    this.txtState.Text = "正在播放。";
                    if (BackgroundAudioPlayer.Instance.Track != null)
                    {
                        this.txtInfo.Text = BackgroundAudioPlayer.Instance.Track.Title;
                    }
                    this.sldVl.Value = BackgroundAudioPlayer.Instance.Volume;
                }
            }

    调试很多次都报错,请问是什么原因,怎么解决。

    先谢谢了

    2013年7月2日 15:58

答案

  • 主程序和Agent不能直接调用资源。你的音频文件需要存到独立存储空间内,然后在Agent中读取出来进行播放。

    • 已标记为答案 Cloud_915 2014年10月31日 14:47
    2013年9月6日 9:21

全部回复