打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
MediaPlayer的生命周期以及状态转换

MediaPlayer类可用于控制播放音频/视频文件和流。关于如何使用这个类的方法的例子可以在VideoView找到。

有关如何使用MediaPlayer的更多信息,请阅读Media Playback开发人员指南

StateDiagram(状态图)

对播放音频/视频文件和流的管理作为一个状态机。下图显示了MediaPlayer的生命周期和以及播放控制的MediaPlayer对象的状态。椭圆代表MediaPlayer对象可能状态。弧线代表MediaPlayer的状态转换。有两种类型的弧线。用单箭头的弧线代表同步的方法调用,而以双箭头代表异步方法调用。



从这个状态图,可以看到,一个MediaPlayer对象有以下状态:

  •  当一个MediaPlayer对象使用new被创建或者调用了reset(),该MediaPlayer对象处于IDLE状态。当调用了release(),该MediaPlayer处于END状态。MediaPlayer对象的生命周期处于这两个状态之间
刚刚创建的MediaPlayer对象与调用reset之后的MediaPlayer对象,存在着一个微小但是很重要的区别,在这两种处于idle状态下MediaPlayer对象,如果调用以下方法会产生程序错误:getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare() ,prepareAsync()如果任何这些方法在一个MediaPlayer对象被创建(通过new创建)时调用,用户提供的回调方法OnErrorListener.onError()将不会被内部播放引擎调用,对象的状态保持不变;但是,如果reset之后这些方法被调用,用户提供回调方法OnErrorListener.onError()将由内部播放器引擎调用并且对象将被转移到错误状态。
建议,当一个MediaPlayer对象不在被使用时,调用该对象的release方法,这样可以确保内部的播放引擎,释放与这个对象相关的所有资源。资源可能包括独占(singleton)资源,例如硬件加速组件。如果调用release失败,可能会引起Mediaplayer后续对象异常。一旦MediaPlayer对象处于end状态,它不能再被使用,并且不可以将该对象返回到其他任何状态。
此外,使用new创建的MediaPlayer对象处于idle状态,而用一个重载的构造方法new出来的MediaPlayer对象不处在idle状态。事实上,如果使用该构造方法成功创建一个MediaPlayer对象,该对象是在Prepared 状态。
  • 一般情况下,一些播放控制操作可能由于各种原因导致失败,例如不支持音频/视频格式,数据错误的音频/视频,分辨率太高,数据流超时等故障。因此,错误报告和状态恢复是在这种情况下一个重要的问题。有时,由于编程错误,在一个invalid 状态下调用MediaPlayer的方法,也可能发生。在所有这些错误的条件下,内部播放引擎调用用户提供OnErrorListener.onError()方法,如果一个OnErrorListener已通过setOnErrorListener(android.media.MediaPlayer.OnErrorListener)预先注册
要注意的是,一旦发生错误,MediaPlayer对象进入错误状态(除了如上所述),即使 error listener没有被application注册。
。为了重用一个处于错误状态的MediaPlayer对象,可以调用reset方法使这个对象从错误状态转换到idle状态
。应用注册一个OnErrorListener来接收来自内部播放引擎传递的错误通知,是一个很好的编程习惯
。在一个invalid状态下,调用例如prepare(), prepareAsync(),或者重载后的setDataSource ,播放引擎会抛出一个 IllegalStateException 来避免程序错误。
  • 调用setDataSource(FileDescriptor), 或者 setDataSource(String), 或者 setDataSource(Context, Uri), 或 setDataSource(FileDescriptor, long, long) 可以将一个MediaPlayer 对象从idle状态转换为Initialized状态 。
。如果在其他任何状态下调用 setDataSource() 都会产生一个 IllegalStateException 异常
。一直监听重载 setDataSource 方法产生的IllegalArgumentException  和IOException是一个很好的编程习惯
  • 一个MediaPlayer对象必须先进入Prepared 状态之后,才可以被启动(started)。
。有两种方法(同步与异步)可以使MediaPlayer对象进入Prepared状态:一种是调用prepare()方(同步),一旦方法被调用,MediaPlayer就进入Prepared状态,方法立刻返回。或者调用prepareAsync()(异步)在该方法返回之前,MediaPlayer 首先进入Preparing状态。 而内部播放引擎会继续等待MediaPlayer准备,直到准备工作完成。当准备完成时或prepare()调用返回,内部播放引擎,然后调用用户提供的回调方法的OnPreparedListener接口,onPrepared(),如果OnPreparedListener通过setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)预先注册。
。需要强调说明的是:Preparing 状态是一个临时状态,如果MediaPlayer对象处于Preparing 状态,调用其他方法,该对象产生的行为时不确定的。
。如果在其他状态调用 prepare() or prepareAsync()会抛出一个IllegalStateException 异常
。如果MediaPlayer对象处于Prepared 状态,例如音频音量,screenOnWhilePlaying,循环次数等属性可以通过调用相应的set方法设置
。要开始播放,则start()必须被调用。start()返回成功,MediaPlayer对象是处于Started 状态。 IsPlaying()可以调用来测试MediaPlayer对象是否处于Started 状态。
。在Started状态下,内部播放引擎会调用用户提供的OnBufferingUpdateListener.onBufferingUpdate()回调方法,如果一个OnBufferingUpdateListener已通过setOnBufferingUpdateListener(OnBufferingUpdateListener)预先注册。该回调方法允许应用程序保存流式音频/视频缓存状态的轨道。
。如果一个对应已经处于Started 状态,再次调用start()将不会对该MediaPlayer对象产生影响
  • 播放可以被暂停会停止,或者调整当前播放的位置。调用 pause() 播放可以被停止。当调用 pause()并成功安徽后,MediaPlayer对象进入到Paused 状态。需要说明的是,状态从Started 进入到Paused ,也可以从Paused 进入到Started 。状态被更新需要花费一定的时间,如果在状态被更新前调用 isPlaying(),可能会返回几秒钟的流媒体数据
。调用start()方法,可以将一个被暂停的MediaPlayer恢复。恢复后开始播放的位置就是该对象被暂停的位置。当调用start()返回后,被暂停的MediaPlayer对象回到Started 状态
。如果一个对象已经处于Paused 状态,调用pause() 将不会对该MediaPlayer对象产生任何影响
  • 调用stop() 将停止一个播放,调用stop()之后,将会导致处于 Started, Paused, Prepared or PlaybackCompleted 状态的对象进入Stopped  状态
。一旦处于Stopped 状态,播放不能启动,直到prepare()或prepareAsync()被调用将MediaPlayer对象重新设置到Prepared状态
。如果一个对象处于Stopped状态,调用stop()不会对该对象产生任何影响
  • 调用seekTo(int)可以调整播放的位置
。虽然同步 seekTo(int)的调用正确的返回,实际seek操作可能需要一段时间才能完成,尤其是对音频/视频流式传输。当实际seek操作完成后,内部播放引擎会调用用户提供OnSeekComplete.onSeekComplete()如果OnSeekCompleteListener已经通过setOnSeekCompleteListener(OnSeekCompleteListener)预先注册。
。需要注意的是 seekTo(int) 也可以在其他的状态被调用,例如Prepared, Paused and PlaybackCompleted 状态
。此外,当前实际的播放位置可以通过调用getCurrentPosition()来获取。这个对应某些应用是很有用的,例如音乐播放器可以保持当前的播放进度。
  • 当播放到达流的末尾时,播放完成为止。
。如果循环模式已被设置为true通过setLooping(boolean),MediaPlayer对象将回到Started状态。
。如果循环模式被设置为false,播放器引擎会调用用户提供的回调方法,OnCompletion.onCompletion(),如果OnCompletionListener通过setOnCompletionListener(OnCompletionListener)预先注册。回调方法的执行代表当前的对象处在PlaybackCompleted状态。
。如果对象处于 PlaybackCompleted 状态,调用start() 可以讲播放重新开始,开始的位置就是声音/视频文件的开始位置

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
android MediaPlayer API
Android MediaPlayer 基础简介
【Android笔记】AndroidMediaPlayer的生命周期
Android MediaPlayer生命周期详解
用MediaPlayer TextureView封装一个完美实现全屏、小窗口的视频播放器
Android开发手记(14) 使用MediaPlayer播放mp3
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服