Android-7.0-MediaPlayer状态机

注:本文参照google apis:
https://developer.android.com/reference/android/media/MediaPlayer.html
MediaPlayer类可用于控制音频/视频文件和流的播放或回放(playback)。

状态图

音频/视频文件和流的播放控制是使用一个状态机进行管理。下图显示了生命周期,并支持播放控制操作驱动的MediaPlayer对象的状态。椭圆表示一个MediaPlayer对象可以驻留在的状态。所述弧线表示驱动对象的状态过渡的重放控制操作。有两种类型的弧线。具有单箭头头部的弧线表示同步方法调用,而那些与双箭头表示异步方法调用。
这里写图片描述
而依据上图分析mediaPlayer的所有状态:

  1. MediaPlayer被创建new方法或者在reset方法调用之后,它处于空闲状态(Idle);release()方法被调用的时候,处于结束状态(end);这两种状态之间是mediaPlayer的生命周期。

    • 创建一个新的MediaPlayer对象,通过new()实现和创建了MediaPlayer对象之后,调用了reset(),这之间有一些微妙但是非常重要的区别。
      – 在以上两种空闲状态的情况下,一些编程错误会调用这些方法: getCurrentPosition(), getDuration(), getVideoHeight(),getVideoWidth(), setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int),prepare() or prepareAsync() 。
      – 区别:如果其中的任何一个方法,在MediaPlayer构造(new方法)之后,立即调用,用户所提供的错误回调方法OnErrorListener.onError()将不会被播放引擎回调同时对象的状态也保持不变,即保持Idle状态。但是如果这些方法是在reset()方法之后调用,用户所提供的内部播放引擎的回调,会被调用。而且MediaPlayer的对象状态也会被转换成Error状态。
    • 建议是这样的,一旦MediaPlayer对象,不再使用。立即调用release()方法,这样,和MediaPlayer关联的播放引擎所使用的资源能得到立即释放。这些资源可能包括单一的硬件硬件加速组件。调用release()失败可能导致后续的MediaPlayer对象实例去依靠软件实现或失败(这句不是很好理解)。一旦MediaPlayer对象在End状态。它将不能再被使用,同时也没有任何方式让它重回到其它状态。
    • 此外,MediaPlayer对象通过new的方式创建是处在空闲状态(Idle).当这些创建是通过某个重载的create()方法创建则不是在空闲(idle)状态。如果通过create()方法成功创建的MediaPlayer处在准备完成Prepared状态。
      一句话总结:不在使用的MediaPlayer对象,要即时释放,调用release方法。
  2. 通常情况下播放控制操作可能由于多种原因而失败,比如不支持的音频视频格式,分辨率过高,流超时,等等。因此错误报告和恢复在这种情况下的一个重要的问题。有时,由于程序错误,也有可能在一些无效状态下调用回放(播放)操作。在所有的这些错误的情况下,内部播放引擎会调用用户提供的OnErrorListener.onError(),前提是用户事先已经通过setOnErrorListener方法设置过一个OnErrorListener。

    • 一个重要的提示,一旦一个错误发生,MediaPlayer对象进入Error状态,即使没有OnErrorListener被注册。
    • 为了重新使用出于Error状态的MediaPlayer对象和从Error状态中恢复。reset()方法能被调用去恢复MediaPlayer对象的空闲状态。
    • 非法状态异常被抛出来阻止程序错误。比如在非法的状态下,调用了prepare(),prepareAsync()或者重载的setDataSource()方法。
  3. 调用 setDataSource(FileDescriptor), or setDataSource(String), or setDataSource(Context, Uri), or setDataSource(FileDescriptor, long, long), or setDataSource(MediaDataSource) 后,MediaPlayer会从空闲(Idle)状态到初始化(init)状态。

    • 非法状态异常抛出:在任何其它状态下被调用
    • 一个好的编程习惯是总是去留心在使用setDataSource()可能抛出的IllegalArgumentException和IoException。
  4. MediaPlayer对象在能被播放之前,必须信进入准备完成状态(prepared)。

    • 有两种方法(同步或者异步)可以使准备完成状态达到。要么调用prepare()方法return后,转换对象的状态到完成状态。要么调用prepareAsync()。prepareAsync()方法retruns后,进入到正在准备状态。然后内部的播放引擎继续做剩下的准备工作,直到准备完成。当准备完成或者prepare()方法return后,内部引擎会调用用户提供的回调方法onPrepared().前提条件是用户事先已经注册了这个接口。此时的MediaPlayer的状态是prepared。
    • 一个重要提示准备中状态(preparing state)是一个瞬间状态。
    • IllegalStateException 被抛出,在其它的任何状态被调用。
    • 在准备完成状态,一些属性比如音频音量,循环等可以通过相应的方法被设置。
  5. 开始播放,start()方法必须被调用。在start()方法调用之后,返回成功。MediaPlayer进入到已经播放状态(started)。isPlaying()可以用来测试MediaPlayer对象是否在已经开始状态started。

    • 当在已经开始状态下,内部的播放引擎会调用内部的用户提供的OnBufferingUpdateListener.onBufferingUpdate(),事先注册过监听。这个回调方法允许应用程序跟踪流媒体的缓冲状态。
    • 当已在已经开始状态下,再次调用start()方法是无效的。比如想通过start()重复调用,来实现重播的功能。
  6. 播放可以被暂停和停止同时当前的播放位置也可以被调整。调用pause()方法 return后,进入已停止状态paused.从已经开始状态转换到暂停状态是在播放引擎中异步发生的。反之,也是一样。也许需要花费一点时间状态被更新在调用isPlaying()。在流内容的情况下,它可能是几秒。

    • 调用start()去恢复一个播放暂停状态的mediaPlayer对象,同时恢复到播放位置到之前暂停的位置。当start()调用完成后,暂停状态的MediaPlayer对象重新恢复到已经开始状态的MediaPlayer对象。
    • 在paused状态下,调用pause()方法无效。
  7. 调用stop()停止播放。同时MediaPlayer在Started,paused,prepared,playbackCompleted状态进入到stopped状态。

    • 一旦处于stopped状态,则直到调用prepare()或prepareAsync()以再次将MediaPlayer对象设置为prepared状态,才能启动播放。
    • 调用stop()对已处于stopped状态的MediaPlayer对象没有影响。
  8. 播放的位置可以调用seekTo(int position)方法进行调整

    • 尽管异步的seekTo()方法能够即时的返回。实际上seek操作可能会耗费一定的时间去完成,尤其是音频视频在转化成流时。当实际的seek操作完成,内部的播放引擎会回调用户提供OnSeekComplete.onSeekComplete(),事前注册过。
    • 请注意,seekTo()方法也可以在其它的状态下调用,比如Prepared,Paused,PlaybackCompleted
    • 此外,实际播放的位置可以调用getCurrentPosition()得到。这个非常有用对音乐播放器类的应用,需要保持跟踪播放的进度。
  9. 当播放达到流的结尾,播放完成

    • 如果循环模式通过setLooping(true)被设置成了true.MediaPlayer将仍然保持在已经开始状态。
    • 如果循环模式设置成了false,播放引擎会调用用户提供的OnCompletion.onCompletion(),事先设置过。此时进入到PlayBackCompleted状态。
    • 播放完成状态,调用start()可以重新播放之前的视频音频资源。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值