Android音视频开发-MediaPlayer的各种状态详解

最近才开始看的Android音视频开发,觉得里面对MediaPlayer的各种状态讲解的比较详细,做了一下笔记:

Android的MediaPlayer专门用于控制视频/音频的文件以及流的播放,有状态机进行管理,相关的状态周期可由10个状态组成,如下图:


图中的椭圆代表 MediaPlayer 驻留的状态,弧代表播放控制且聚动 MediaPlayer 状态进行过渡.有两种类型的弧,单箭头弧表示的是同步函数调用,双箭头弧表示的是异步函数调用。

从图中,我们能看到MediaPlayer 有下面的一些状态。

ldle状态及End状态

在 MediaPlayer 创建实例或者调用 reset 函数后,播放器就被创建了,这时处于ldle (就 绪)状态,调用 release函数后,就会变成 End(结束)状态,在这两种状态之间的就是 MediaPlayer的生命周期。

Error 状态

在构造一个新MediaPlayer 或者调用reset 函数后,上层应用程序调用的getCurrentPosition、 getVideoHeight 、 getDuration 、 getVideoWidth 、 setAudioStreamType(int)、 setLooping(boolean)、 setVolume(float,float)、 pause、 start、 stop、 seekTo(int)、 prepare、 prepareAsync 这些函数如果会出错。如果调用 reset 函数后再调用它们,用户提供的回调函数OnErrorListener.onError 将触发 MediaPlayer 状态到 Error(错误)状态,所以一旦不再使用 MediaPlayer,就需要调用 release 函数,以便 MediaPlayer 资源得到合理释放。

当 MediaPlayer 处于End(结束)状态时,它将不能再被使用,这时不能再回到 MediaPlayer的其他状态,因为本次生命周期已经终止。

由于支持的音视频格式分辨率过高,输入数据流超时,或者其他各种各样的原因将导致播放失败。在这种错误的条件下,如果用户事先通过setOnErrorListener 注册过OnErrorListener, 当 player 内部调用OnErrorListener.onError 回调函数时,将会返回错误信息。一旦有错误, MediaPlayer 会进入 Error(错误)状态,为了重新使用MediaPlayer,调用 reset 函数,这时将重新恢复到Idle(就绪)状态,所以需要给 MediaPlayer 设置错误监听,出错后就可以从播放器内部返回的信息中找到错误原因。

Initialized 状态

当调用 setDataSource(FileDescriptor)s setDataSource(String)、 setDataSource(Context, Uri)、 setDataSource(FileDescriptor, long, long)其中一个函数时,将传递 MediaPlayer 的 Idle 状态变成 Initialized(初始化)状态,如果 setDataSource 在非 Idle状态时调用,会抛出 IllegalStateException 异常。当重载setDataSource时,需要抛出IlegalArgumentException 和 IOException这两个异常。 5. Prepared 状态

MediaPlayer 有两种途径到达 Prepared 状态,一种是同步方式,另一种是异步方式。同步方式主要使用本地音视频文件,异步方式主要使用网络数据,需要缓冲数据。调用 prepare (同步函数)将传递MediaPlayer 的 Initialized状态变成Prepared状态,或者调用 prepareAsync (异步函数)将传递MediaPlayer 的 Initialized状态变成Preparing状态,最后到Prepared状态。 如果应用层事先注册过setOnPreparedListener ,播放器内部将回调用户设置的 OnPreparedListener 中的 onPrepared 回调函数。注意,Preparing是一个瞬间状态(可理解为时间比较短)。

Started 状态

在 MediaPlayer 进入 Prepared 状态后,上层应用即可设置一些属性,如音视频的音量、 sereenOnWhilePlaying、 looping 等。在播放控制开始之前,必须调用 start 函数并成功返回, MediaPlayer的状态开始由 Prepared状态变成Started状态。当处于 Started状态时,如果用户事先注册过setOnBufferingUpdateListener,播放器内部会开始回调OnBuferingUpdateListener.on BuferingUpdate,这个回调函数主要使应用程序保持跟踪音视频流的 bufering(缓冲) status如果MediaPlayer 已经处于 Started状态,再调用start函数是没有任何作用的。

Paused状态

MediaPlayer在播放控制时可以是Paused (暂停)和Stopped (停止)状态的,且当前的播 放时进度可以被调整,当调用 MediaPlayer.pause函数时,MediaPlayer 开始由 Started状态变成 Paused状态,这个从 Started 状态到Paused状态的过程是瞬间的,反之在播放器内部是异步过程的。在状态更新并调用isPlaying函数前,将有一些耗时。已经缓冲过的数据流,也要耗费数秒。

当start函数从 Paused 状态恢复回来时,playback恢复之前暂停时的位置,接着开始播放,这时MediaPlayer的 Paused状态又变成Started状态。如果MediaPlayer已经处于 Paused状态,这时再调用 pause函数是没有任何作用的,将保持Paused状态。

Stopped 状态

当调用stop 函数时,MediaPlayer 无论正处于Started 、 Paused 、Prepared 或 PlaybackCompleted 中的哪种状态,都将进入 Stopped状态。一旦处于Stopped状态,playback将不能开始,直到重新调用 prepare 或 prepareAsync函数,且处于Prepared 状态时才可以开始。

如果 MediaPlayer 已经处于 Stopped状态了,这时再调用 stop函数是没有任何作用的,将 保持Stopped状态。

在 Seek操作完成后,如果事先在MediaPlayer 注册了setOnSeekCompleteListener,播放器内部将回调OnSeekComplete.onSeekComplete函数。当然seekTo函数也可以在其他状态下被调用,如 Prepared、 Paused 及 PlaybackCompleted 状态。

PlaybackCompleted 状态

当前播放的位置可以通过 getCurrentPosition函数获取,通过 getCurrentPosition函数,可以跟踪播放器的播放进度。 当MediaPlayer 播放到数据流的末尾时,一次播放过程完成。在 MediaPlayer 中事先调用 setLooping(boolean)并设置为true,表示循环播放,MediaPlayer 依然处于Started状态。如果调用setLooping(boolean)并设置为 false(表示不循环播放),并且事先在 MediaPlayer 上注册过setOnCompletionListener,播放器内部将回调OnCompletion.onCompletion 函数,这就表明MediaPlayer 开始进入PlaybackCompleted(播放完成)状态。当处于 PlaybackCompleted 状态时,调用start函数,将重启播放器从头开始播放数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容