Frage

So I have a problem with the Background Audio Playback agent in WP 7.5, where I think it is getting terminated by the OS randomly during playback.

I have an app which implements a BAP agent which plays a number of mp3 files based the selected chapter in UI. Each chapter has multiple verses, these verses have an associated mp3 file in isolated storage.

Once a chapter has been selected in the UI and the user presses the play button BackgroundAudio.Instance.Play() is called and the first verse (mp3 file) for that chapter is loaded as an AudioTrack. When the track has ended the next track is loaded in the OnPlayStateChanged event method under the TrackEnded state.

I also have some logic in the TrackEnded which checks if the end of the chapter has been reached (i.e. the last mp3 file for the current chapter has been played) and if so the first mp3 file for the next chapter will retrieved.

Now all the above works fine when using the Windows Phone 7 Emulator (both 512Mb and 256Mb Emulators), the mp3 files are played correctly and when the end of a chapter has been reached the next mp3 file for the next chapter is correctly loaded and played.

The problem I encounter is when I deploy this app to a Win 8 Device (Lumia 920), the audio starts playing fine and the suddenly and seemingly randomly the audio stops! No error messages, the app does NOT crash, just the Audio Stops playing. Also when I click on the UVC buttons on the device NO AudioTrack info is displayed as is the case during audio playback or audio has been paused (just the volume info shows).

I have no idea what’s going on, I think the OS may be terminating the Background Audio Playback agent but I have no idea why (I don’t think I am reaching any of the memory limitations but I can not confirm this as I don’t know how to check if I am).

Any advice/help will be appreciated.

Thanks

Update 14/01/14

To confirm that the memory limit of 15Mb(WP7) and 20Mb(WP8) was not being reached by my BAP I implemented some code which logged the current memory usage of the BAP at various stages through out its execution.

The memory usage does not reach anywhere near the limits imposed by the OS on the BAP, the peak i reach is 7Mb the issue I described above is still occurring, I can see from the log that the next track has already been set but the state Trackready is never hit, also no exceptions/errors are thrown. This has really stumped me!

Update 15/01/14 Below is an example of how I have implemented the 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

    }

Update 24/01/2014 ISSUE RESOLVED

I finally got some time to get around to attempting what @Soonts recommended in the answer I marked as the answer, and firstly I'm using a WP8 device so I skipped the first setp that he mentioned, next i did as was mentioned in step 2 and again the max memory usage was only 8Mb.

Then a few days back there was an update for my WP8 device (WP8 Update 3), after I installed this update I attempted to reproduce the problem and guess what! The issue DOES NOT OCCUR ANY MORE!, I had my audio on continuous play for over an hour with no issues! also the memory usage was stable at around 8Mb. So it looks like there may have been a silent update to the BG Audio.

The reason why I marked @snoots answer as the answer was because he mentioned in that answer that the issue may be fixed by a silent update.

War es hilfreich?

Lösung 2

If I were you, I would probably do the following, in that order:

  1. Ensure you have the latest OS updates. They have silently fixed some BAP-related memory issues in their 7.8 update. If you're not using the latest OS, upgrade and try to reproduce.
  2. Place breakpoints in every place of your GUI process code that interacts with BAP, to make sure you’re not mistakenly calling e.g. BackgroundAudioPlayer.Stop() or BackgroundAudioPlayer.Track=null, try to reproduce.
  3. Instead of “logging current memory usage of the BAP at various stages”, in static constructor of some agent class, create a thread that, in the endless loop, appends to some CSV file in the isolated storage, logging current timestamp + current memory , then sleeps for 500-1000 milliseconds. Reproduce the problem, use ISETool.exe to download the log, use Excel to build the RAM usage graph…
  4. If (3) won’t show RAM usage approaching the limit, Implement tracing to either isolated storage or network (BTW, I’ve implemented a SysLog RFC 5426 client in my WP7 code, and installed free software called “SysRose Syslog Desktop” on my PC), then try to do printf-style debugging.

Andere Tipps

  1. This may happen on unhandled exceptions. Subscribe for Application.Current.UnhandledException (and if you're using async-await for TaskScheduler.UnobservedTaskException) and log them somewhere. Also, override OnError method of your agent, and log.

  2. This may happen if forget to call BackgroundAgent.NotifyComplete() after you've finished processing the requests (i.e. for player agent, the OnPlayStateChanged and OnUserAction). In this case, the OS consludes you was unable to process the request in a timely manner, and terminates the BAP process.

  3. RAM issues, but you've figured it out.

P.S. Here's the relevant part of my Sky.fm player application. It doesn't play local MP3s , instead it streams the music from the Internets, however the player agent code should be more or less the same.

/// <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 );
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top