Android MediaPlayer.getCurrentPosition()和MediaPlayer.getDuration()是否有未记录的无效状态?

时间:2015-01-09 10:25:06

标签: android xamarin.android android-mediaplayer

我有一个Androids MediaPlayer的实例,我试图尽可能好地跟踪当前的状态。

当我使用Xamarin(monodroid)时,我不能使用由danielhawkes(https://gist.github.com/danielhawkes/1029568)编写的包装器,但必须自己编写。我最后得到了那个:

namespace MyApp.UI.Droid
{
    public delegate void InternalStatusChangedEventHandler(object sender, MediaPlayerInternalStatusEventArgs e);

    public class MediaPlayerWrapper : Android.Media.MediaPlayer
    {
        public event InternalStatusChangedEventHandler InternalStatusChanged;

        private MediaPlayerStatus internalStatus;
        public MediaPlayerStatus InternalStatus {
            get { return internalStatus; }
            set {
                internalStatus = value;

                if (InternalStatusChanged != null)
                    InternalStatusChanged(this, new MediaPlayerInternalStatusEventArgs(internalStatus));
            }
        }

        public MediaPlayerWrapper() : base() {
            InternalStatus = MediaPlayerStatus.IDLE;

            Prepared += (object sender, EventArgs e) => InternalStatus = MediaPlayerStatus.PREPARED;
            Error += (object sender, ErrorEventArgs e) => InternalStatus = MediaPlayerStatus.ERROR;

            Completion += (object sender, EventArgs e) => {
                if (!Looping)
                    InternalStatus = MediaPlayerStatus.PLAYBACK_COMPLETED;
            };
        }

        public override void Reset ()
        {
            InternalStatus = MediaPlayerStatus.IDLE;
            base.Reset ();
        }

        public override void SetDataSource (Android.Content.Context context, Android.Net.Uri uri)
        {
            InternalStatus = MediaPlayerStatus.INITIALIZED;
            base.SetDataSource (context, uri);
        }

        public override void SetDataSource (Android.Content.Context context, Android.Net.Uri uri, System.Collections.Generic.IDictionary<string, string> headers)
        {
            InternalStatus = MediaPlayerStatus.INITIALIZED;
            base.SetDataSource (context, uri, headers);
        }

        public override void SetDataSource (Java.IO.FileDescriptor fd)
        {
            InternalStatus = MediaPlayerStatus.INITIALIZED;
            base.SetDataSource (fd);
        }

        public override void SetDataSource (Java.IO.FileDescriptor fd, long offset, long length)
        {
            InternalStatus = MediaPlayerStatus.INITIALIZED;
            base.SetDataSource (fd, offset, length);
        }

        public override void SetDataSource (string path)
        {
            InternalStatus = MediaPlayerStatus.INITIALIZED;
            base.SetDataSource (path);
        }

        public override void PrepareAsync ()
        {
            InternalStatus = MediaPlayerStatus.PREPARING;
            base.PrepareAsync ();
        }

        public override void Prepare ()
        {
            InternalStatus = MediaPlayerStatus.PREPARED;
            base.Prepare ();
        }

        public override void Start ()
        {
            InternalStatus = MediaPlayerStatus.STARTED;
            base.Start ();
        }

        public override void Pause ()
        {
            InternalStatus = MediaPlayerStatus.PAUSED;
            base.Pause ();
        }

        public override void Stop ()
        {
            InternalStatus = MediaPlayerStatus.STOPPED;
            base.Stop ();
        }

        public override void Release ()
        {
            InternalStatus = MediaPlayerStatus.END;
            base.Release ();
        }
    }

    public class MediaPlayerInternalStatusEventArgs : EventArgs
    {
        public MediaPlayerInternalStatusEventArgs(MediaPlayerStatus status)
        {
            this.Status = status;
        }

        public MediaPlayerStatus Status { get; private set; }
    }
}

经过一段时间的测试并重新阅读文档(http://developer.android.com/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States)后,我偶然发现了一件事:

报告方法MediaPlayer.getCurrentPosition()无法在实例的Error状态中调用。但是在我的例子中,如果玩家处于OnError状态,它也会触发Idle处理程序。

与方法MediaPlayer.getDuration()相同。据报道,在实例的Idle, Initialized, Error状态下调用无效。但是在我的例子中,如果玩家处于OnError状态,它也会触发PREPARING处理程序。

这里的文档有误吗?或者我在包装中遗漏了什么?对于MonoDroid来说这可能是特别的吗?

2 个答案:

答案 0 :(得分:0)

在调用getCurrentPosition()之前检查instance.isPlaying()或isPaused()。

仅在onPrepared()中调用getDuration()一次并存储该值。

正如其他主题中所提到的,MediaPlayer状态处理是一个很好的选择。 没有getState()方法。

不仅如此,您还无法为其添加编解码器。此外,网络流媒体将受到严重影响(特别是对于youtube)。

它过早地发布了,就像Android的大部分内容一样,现在却被它的坏人所困扰。

在我的下一个项目中,我将使用任何其他可扩展的敏感开源播放器,如VLC。

答案 1 :(得分:0)

Preparing状态未被提及为任何方法调用的无效状态,但它通常是不稳定和未定义的状态来调用任何内容。

正如文档中稍早提到的那样:

  

重要的是要注意,准备状态是一种瞬态,并且在MediaPlayer对象处于准备状态时调用任何具有副作用的方法的行为是未定义的。