windows-phone-7 - 后台音频播放代理在播放过程中终止 Windows Phone 7.5

标签 windows-phone-7 windows-phone background-audio

所以我在 WP 7.5 中遇到了后台音频播放代理的问题,我认为它在播放过程中被操作系统随机终止。

我有一个应用程序,它实现了一个 BAP 代理,该代理根据 UI 中选定的章节播放多个 mp3 文件。每章都有多个经文,这些经文在独立存储中都有一个关联的 mp3 文件。

在 UI 中选择章节并且用户按下播放按钮后,将调用 BackgroundAudio.Instance.Play(),并且该章节的第一节(mp3 文件)将作为AudioTrack。当轨道结束时,下一首轨道将在 TrackEnded 状态下的 OnPlayStateChanged 事件方法中加载。

我在 TrackEnded 中还有一些逻辑,它检查是否已到达章节末尾(即,当前章节的最后一个 mp3 文件已播放),如果是,则检查第一个 mp3 文件将检索下一章。

现在,使用 Windows Phone 7 模拟器(512Mb 和 256Mb 模拟器)时,上述所有操作都可以正常工作,mp3 文件可以正确播放,并且当到达章节末尾时,下一章的下一个 mp3 文件也可以正确播放已加载并播放。

我遇到的问题是,当我将此应用程序部署到 Win 8 设备 (Lumia 920) 时,音频开始正常播放,然后音频突然且看似随机地停止了!没有错误消息,应用程序不会崩溃,只是音频停止播放。此外,当我单击设备上的 UVC 按钮时,不会显示 AudioTrack 信息,就像音频播放期间或音频已暂停的情况一样(仅显示音量信息)。

我不知道发生了什么事,我认为操作系统可能正在终止后台音频播放代理,但我不知道为什么(我认为我没有达到任何内存限制,但我无法确认这一点我不知道如何检查我是否是)。

任何建议/帮助将不胜感激。

谢谢

更新 2014 年 1 月 14 日

为了确认我的 BAP 未达到 15Mb(WP7) 和 20Mb(WP8) 的内存限制,我实现了一些代码,记录了 BAP 在执行过程中各个阶段的当前内存使用情况。

内存使用量没有达到操作系统对 BAP 施加的限制附近的任何地方,我达到的峰值是 7Mb,我上面描述的问题仍然发生,我可以从日志中看到下一个轨道已经设置但状态 Trackready 永远不会被命中,也不会抛出异常/错误。这实在是难倒了我!

更新 2014 年 1 月 15 日 下面是我如何实现 BAP 的示例:

    public AudioPlayer()
    {

       if (!_classInitialized)
        {
            _classInitialized = true;
            // Subscribe to the managed exception handler
            Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                Application.Current.UnhandledException += AudioPlayer_UnhandledException;
            });
            lastPlayedVerse = currentVerseNumber;

        }
    }

     /// Code to execute on Unhandled Exceptions
    private void AudioPlayer_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
    {
    //Helper class to help log any exceptions
        IsolatedStore.WriteToIS("unhandeled Ex: " + e.ExceptionObject.Message, IsolatedStore.MemLogFileName);
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // An unhandled exception has occurred; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

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

        //Helper class to help log any exceptions
        IsolatedStore.WriteToIS("OnError Called: " + error.Message, IsolatedStore.MemLogFileName);

        if (isFatal)
        {
            Abort();
        }
        else
        {
            NotifyComplete();
        }

    }

    protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
    {
        switch (playState)
        {
            case PlayState.TrackEnded:

                track = null;
    IsolatedStore.AppendToFileIS(string.Format("Track Ended::Time: {0}",DateTime.Now.ToLongTimeString()), IsolatedStore.MemLogFileName);

                #region Track Ended logic
                //IN here I have some logic to determine what the next track should be and then I call a function that returns an AudioTrack
                 player.Track = GetNextTrack();  //this method returns an AudioTrack                  
                #endregion
                break;
            case PlayState.TrackReady:
                IsolatedStore.AppendToFileIS(string.Format("Track Ready::Time: {0}, Track: {1}", DateTime.Now.ToLongTimeString(),track.Title), IsolatedStore.MemLogFileName);

                //Put this try catch in here becoz i thought that this is where the issue was (not sure if its needed as any exception should be caught by the AudioPlayer_UnhandledException function.
                try
                {
                    player.Play();
                }
                catch (Exception ex)
                {

                    IsolatedStore.AppendToFileIS(string.Format("Track Ready play exception: {0}", ex.Message), IsolatedStore.MemLogFileName);

                }           
                break;

        }

        NotifyComplete();
    }

    protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
    {
        switch (action)
        {
            case UserAction.Play:
                if (player.PlayerState != PlayState.Playing)
                {
                    IsolatedStore.AppendToFileIS(string.Format("UA-PLAY::Time: {0}, Track: {1}", DateTime.Now.ToLongTimeString(),track.Title), IsolatedStore.MemLogFileName);
                    player.Play();

                }
                break;
        }

        NotifyComplete();
    }

    private AudioTrack GetNextTrack(int audioType2Get, string filePath, int verserNum, bool incrementTrackCount)
    {

        #region Memusage

        //Code to log the memory usage
        long currMemUsage = (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
        currMemUsage = (currMemUsage / 1024) / 1024;
        long peakMemUsage = (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
        peakMemUsage = (peakMemUsage / 1024) / 1024;
        IsolatedStore.AppendToFileIS(string.Format("Getting Track-Time: {0}, Curr:{1}, Track: {2}", DateTime.Now.ToLongTimeString(), currMemUsage, verserNum), IsolatedStore.MemLogFileName);

        #endregion
        AudioTrack track = null;
        #region AudioTrack Set region
        //Some logic to return the AudioTrack
        #endregion

    }

更新 2014 年 1 月 24 日问题已解决

我终于有时间尝试一下@Soonts在我标记为答案的答案中推荐的内容,首先我使用的是WP8设备,所以我跳过了他提到的第一个setp,接下来我按原样做了在步骤 2 中再次提到最大内存使用量仅为 8Mb。

几天前,我的 WP8 设备有更新 (WP8 Update 3) ,安装此更新后,我尝试重现该问题,你猜怎么着!这个问题不再发生!,我的音频连续播放了一个多小时,没有任何问题!内存使用也稳定在8Mb左右。所以看来 BG Audio 可能进行了静默更新。

我之所以将@snoots答案标记为答案,是因为他在该答案中提到该问题可以通过静默更新来解决。

最佳答案

  1. 这可能发生在未处理的异常上。订阅Application.Current.UnhandledException(如果您对TaskScheduler.UnobservedTaskException使用async-await)并将它们记录在某处。另外,重写代理的 OnError 方法并记录。

  2. 如果在处理完请求后忘记调用BackgroundAgent.NotifyComplete()(即对于玩家代理,OnPlayStateChanged 和OnUserAction),可能会发生这种情况。在这种情况下,操作系统认为您无法及时处理请求,并终止 BAP 进程。

  3. RAM 问题,但您已经解决了。

附注这是我的 Sky.fm 播放器应用程序的相关部分。它不播放本地 MP3,而是从 Internet 传输音乐,但播放器代理代码应该大致相同。

/// <summary>This class wraps AudioPlayerAgent API into the async-friendly abstract class.</summary>
/// <remarks>Logging and exception handling are added, as well.</remarks>
public abstract class PlayerAgentAsync: AudioPlayerAgent
{
    static PlayerAgentAsync()
    {
        UnhandledExceptionHandler.subscribe();
    }

    public PlayerAgentAsync()
    {
        Logger.info( "constructed" );
    }

    protected override void OnError( BackgroundAudioPlayer player, AudioTrack track, Exception ex, bool isFatal )
    {
        if( isFatal )
        {
            BackgroundErrorNotifier.addError( ex );
            ex.log();
            Abort();
        }
        else
        {
            ex.logWarning();
            try
            {
                // Force the track to stop 
                // http://blogs.msdn.com/b/wpukcoe/archive/2012/02/11/background-audio-in-windows-phone-7-5-part-3.aspx
                player.Track = null;
            }
            catch (System.Exception ex2)
            {
                ex2.logWarning( "Exception while trying to stop da playa" );
            }
            NotifyComplete();
        }
    }

    /// <summary>Called when the play state changes, except for the error state.</summary>
    protected override async void OnPlayStateChanged( BackgroundAudioPlayer player, AudioTrack track, PlayState playState )
    {
        Logger.info( "new playState = {0}", playState.ToString() );

        try
        {
            await this.playStateChangedAsync( player, track, playState ).ConfigureAwait( false );
            NotifyComplete();
        }
        catch (System.Exception ex)
        {
            this.onException( ex );
        }
    }

    /// <summary>Called when the user requests an action using some application-provided UI or the Universal Volume Control (UVC) and the application has requested notification of the action.</summary>
    protected override async void OnUserAction( BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param )
    {
        Logger.info( "action = {0};", action.ToString() );

        try
        {
            await this.userActionAsync( player, track, action, param ).ConfigureAwait( false );
            NotifyComplete();
        }
        catch( System.Exception ex )
        {
            this.onException( ex );
        }
    }

    private void onException( Exception ex )
    {
        if( ex.shouldBeIgnored() )
        {
            ex.logWarning();
            this.NotifyComplete();
            return;
        }
        ex.log();
        BackgroundErrorNotifier.addError( ex );
        this.Abort();
    }

    protected override void OnCancel()
    {
        Logger.trace();
        base.OnCancel();
    }

    /// <summary>Handle OnPlayStateChanged asyncronously.</summary>
    /// <param name="player">The Microsoft.Phone.BackgroundAudio.BackgroundAudioPlayer.</param>
    /// <param name="track">The track playing at the time that the play state changed.</param>
    /// <param name="playState">The new state of the player.</param>
    protected abstract Task playStateChangedAsync( BackgroundAudioPlayer player, AudioTrack track, PlayState playState );

    /// <summary>Handle OnUserAction asyncronously</summary>
    /// <param name="player">The Microsoft.Phone.BackgroundAudio.BackgroundAudioPlayer.</param>
    /// <param name="track">The track playing at the time of the user action.</param>
    /// <param name="action">The action that the user has requested.</param>
    /// <param name="param">The data associated with the requested action.</param>
    protected abstract Task userActionAsync( BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param );
}

关于windows-phone-7 - 后台音频播放代理在播放过程中终止 Windows Phone 7.5,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20990638/

相关文章:

windows-phone-7 - WP7 无效的跨线程访问 - ScheduledTaskAgent

c# - 文本框,不带重音符号的搜索(忽略重音符号)

.net - Mango Update 中新的 WP7 API 列表?

c# - UWP 后台音频失败,因为 RPC 服务器不可用

windows-phone-7 - 当应用程序暂停时对 AudioPlayerAgent 中的 UserAction 使用react

audio - UWP Windows 10 JS - 直接编译到我的设备时后台音频工作,但从商店打开时不工作

c# - 无法使用以下代码创建主磁贴

windows-phone-7 - 在 WP7 中编辑日期有哪些选项?

c# - Windows Phone 7 上的 Protobuf-net

c# - 在 map 上作为图钉的图像 - Windows Phone 8