我有一个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来说这可能是特别的吗?
答案 0 :(得分:0)
在调用getCurrentPosition()之前检查instance.isPlaying()或isPaused()。
仅在onPrepared()中调用getDuration()一次并存储该值。
正如其他主题中所提到的,MediaPlayer状态处理是一个很好的选择。 没有getState()方法。
不仅如此,您还无法为其添加编解码器。此外,网络流媒体将受到严重影响(特别是对于youtube)。
它过早地发布了,就像Android的大部分内容一样,现在却被它的坏人所困扰。
在我的下一个项目中,我将使用任何其他可扩展的敏感开源播放器,如VLC。
答案 1 :(得分:0)
Preparing
状态未被提及为任何方法调用的无效状态,但它通常是不稳定和未定义的状态来调用任何内容。
正如文档中稍早提到的那样:
重要的是要注意,准备状态是一种瞬态,并且在MediaPlayer对象处于准备状态时调用任何具有副作用的方法的行为是未定义的。