解读MediaPlayer原文

来源:互联网 发布:顺德出格软件 编辑:程序博客网 时间:2024/04/28 14:59

原文地址

手动翻译+有道词典,英文水平有限,重在理解,不喜勿喷!2017/07/02

MediaPlayer类用来控制音视频文件或流的播放。
学习MediaPlayer时把几种状态机制弄明白是至关重要的,官方给出的状态图如下:
image

音视频或流的播放控制被管理为一种状态机。上面这幅图描述了一个通过支持播放控制操作创建的MediaPlayer对象的生命周期和状态。椭圆代表MediaPlayer对象能够处于的状态。弧形代表使MediaPlayer对象状态改变的播放控制操作。有两种类型的弧线。具有单箭头的头弧线表示同步方法调用,而那些具有双箭头表示头异步方法调用。

  • 当MediaPlayer对象通过new()创建或调用reset()方法,就处于Idle空闲状态;当release()方法调用后就处于End状态。
    -MediaPlayer对象的生命周期就是在这两种状态之间。
  • 在新构造的MediaPlayer对象和一个调动reset()方法之后的的MediaPlayer对象之间有个微妙担忧很重要的不同之处。这个不同之处就是在这两种情况(1.通过构造创建一个MediaPlayer 2.MediaP对象调用reset())下的Idle状态时调用getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() 或 prepareAsync() 等方法是的程序错误。
  • 如果在通过构造方法创建一个MediaPlayer对象后即刻调用任何以上的方法,那么回调方法 OnErrorListener.onError() 不会被内部的播放器引擎调用,而且MediaPlayer对象的状态也不会改变;但是如果在reset()方法之后再去调用这些方法,那么内部的播放器引擎就会调用onErrorListener.onError()方法并且MediaPlayer对象会变成Error状态。
  • 官方推荐一旦MediaPlayer对象不再使用,就要立刻调用release()方法,这样就内部播放引擎和MediaPlayer对象相关联的资源就能得到立刻释放。资源可能包括单例资源,如硬件加速组件和调用release()可能导致MediaPlayer对象的后续实例回滚到软件安装或完全失败。一旦MediaPlayer对象处于End状态就不能在使用了,而且也不能回到其他状态。
  • 此外,MediaPlayer对象一旦通过new创建就处于Idle状态,而那些通过重组Create()放到创建的对象并不Idle状态。实际上通过create方法成功创建的对象已经处于Prepare状态了
  • 一般来说可能有各种各样的原因导致播放控制操作失败,例如不支持的音视频格式,错误的音视频,太高的分辨率,流超市等等。在这些情况下,报错和恢复是及其重要的。由于程序错误,在无效的状态下调用控制操作导致报错时有发生。在所有这些错误情况下,如果OnErrorListener提前通过setOnErrorListener注册过,呢么么内部的播放引擎就会调用OnErrorListener.onError()
  • 需要注意的是,一旦出现错误,MediaPlayer对象将进入错误状态(除了上面提到的),即使错误listener 没有被应用程序注册。
  • 为了重用处于错误状态的MediaPlayer对象,并从Error装中恢复过来,可以调用reset()来将对象恢复到它的Idle状态。
  • 应用中注册OnErrorListener观察内部播放器引擎的错误通知一个很好的编程习惯
  • 在无效状态时调用prepare,prepareAsync()或重载setDataSource方法时抛出IiieagalStateException非法状态异常用来保护程序。
  • 调用 setDataSource(FileDescriptor), 或 setDataSource(String),或 setDataSource(Context, Uri), 或 setDataSource(FileDescriptor, long, long), 或setDataSource(MediaDataSource) 等方法MediaPlayer对象从Idle空闲状态转化为Initialized初始化状态。
  • 在非Idle空闲状态调用setDataSource()方法会抛出非法状态异常IllegalStateException
  • MediaPlayer对象开始播放前必须先进入到Prepared准备状态
  • 有两种方法(同步、异步)进入的Prepared状态:一种是调用prepare()(同步的),异步prepare()方法调用返回,MediaPlayer就变成PrePared状态,另一种就是调用prepareAsync()(异步的),它在调用返回(几乎是立刻返回)之后首先将对象变成到Preparing状态,而内部播放器引擎则继续处理其余的准备工作,直到准备工作完成为止(后变成Prepared状态)。当准备工作完成或prepare()方法返回时,内部播放引擎就会调用一个onPreparedListener接口的onPrepared()方法,当然前提是这个OnPrepaerListener已经通多setOnpreparedLister提前注册过
  • 需要注意的是Prepareing状态是一个瞬间状态或者理解成一个过渡状态,在Preparing状态调用任何方法都是无效的(undefined)
  • 其他状态下调用prepare()和prepareAsync()都会抛出非法状态异常
  • 在Prepared状态,能够通过调用相应的设置方法设置音视频音量,屏幕播放,循环播放等属性
  • 调用start()方法才能播放。start()方法成功调用后,MediaPlayer对象就处于Started状态。在Started状态可以调用isPlaying()方法看是否在播放中。
  • 在Started状态,内部的播放引擎在提前通过注册setOnBufferingUpdateListener方法可以调动OnBufferingUpdateListener.onBufferingUpadae()回调方法,这个回调方法能使应用跟踪音视频的缓冲状态
  • 已经处于Started状态的MediaPlayer对象使用start()方法式无效的
  • 播放能够暂停和停止,当前播放位置也能调整。通过pause()方法暂停播放。pause()方法返回时,播放器处于Paused状态。注意从Started状态到Paused状态的转变,反之亦然,在播放器引擎中异步发生。在状态更新前调用isPlaying()方法可能会需要一些时间在流内容的情况下,可能需要几秒的时间。
  • 调用start()来恢复暂停的MediaPlayer对象的播放,恢复的播放位置与暂停的位置是一样的。当对start()的调用返回时,暂停的MediaPlayer对象将返回到Started 状态。
  • 对已经处于暂停状态的MediaPlayer对象 调用pause()无效。
  • 调用stop()停止播放,并在Started, Paused, Prepared 或 PlaybackCompleted会使MediaPlayer进入停止状态。
  • 一旦处于Stopped状态,除非在prepare()或prepareAsync()被调用来将MediaPlayer对象再次设置为准备状态时,才可以启动播放。
  • 调用stop()对已经处于停止状态的MediaPlayer对象无效。
  • 播放位置可以通过调用seekTo(long、int)进行调整。
  • 尽管异步调用(long、int)调用会立即返回,但实际的查找操作可能需要一段时间才能完成,特别是对于音频/视频的流媒体播放。当seek操作实际完成是,内部播放引擎会在提前注册setOnSeekCompleteListener(OnSeekCompleteListener)回调OnSeekComplete.onSeekComplete()方法
  • 请注意,在其状态也可以调用seekTo(long、int),比如准备、暂停和回放状态。当在这些状态中调用seekTo(long、int)时,如果流有视频并且请求的位置是有效的,就会显示一个视频帧。
  • 此外,可以通过调用getCurrentPosition()来检索实际的当前播放位置,这对于需要跟踪回放进程的音乐播放器等应用程序是有帮助的。
  • 当播放到达流的末尾时,播放就完成了
  • 如果将循环模式设置为使用set循环(boolean),那么MediaPlayer对象将保持在Started状态。
  • 如果将循环模式设置为false,播放引擎会调OnCompletion.onCompletion(),担任前提也是提前通过setONCompletionListener注册
  • 在PlaybackCompleted 状态下,调用start()可以从音频/视频源的开始重新播放。
原创粉丝点击