Android MediaPlayer 基础简介
本文链接: android mediaplayer 基础简介
简单介绍mediaplayer的基本概念,状态,常用的方法与监听器。
什么是mediaplayer
mediaplayer类可以用来播放音视频文件,或者是音频流。开发者可以用它来播放本地音频,或者是网络在线音频。
mediaplayer属于android.media
包。
mediaplayer的状态
播放控制由状态机控制。在日常生活中,我们常见的音频状态有播放中,暂停,停止,缓冲等等。
mediaplayer的状态有如下几种:
- idle
- end
- error
- initialized
- preparing
- prepared
- started
- stopped
- paused
- playbackcompleted
状态的切换参考官方图例。
这里稍微解释一下状态转换图片。椭圆代表mediaplayer可能停留的状态。椭圆之间的箭头表示方法调用,状态切换的方向。单箭头表示方法同步调用,双箭头表示异步调用。
从图中我们可以看出状态切换的路径和涉及到的方法。
idle与end状态
当new一个mediaplayer或者调用了reset方法,当前mediaplayer会处于idle状态。调用release后,会处于end状态。在这2个状态之间的状态可以看做是mediaplayer对象的生命周期。
在新创建mediaplayer和调用reset的mediaplayer之间有一些细微的差别。
这两种情况都处于idle状态,调用 getcurrentposition(), getduration(), getvideoheight(), getvideowidth(), setaudioattributes(android.media.audioattributes), setlooping(boolean), setvolume(float, float), pause(), start(), stop(), seekto(long, int), prepare() 或 prepareasync()方法都会抛出错误,如果是新实例化的mediaplayer,不会回调 onerrorlistener.onerror();但如果是reset后的mediaplayer,会回调 onerrorlistener.onerror()并且转换到error状态。
如果mediaplayer对象不再使用了,立即调用release()方法,释放内部播放器占用的资源。这些资源可能是唯一的,比如硬件加速组件。如果调用release失败,可能会引起一连串的mediaplayer实例失效。当mediaplayer处于end状态,它就不能再转移到其它状态了。
new一个mediaplayer,处于idle状态。如果用create方法创建实例,当创建完成时处于prepared状态。
发生错误
一些情形可能会让mediaplayer操作失败,比如不支持的音视频格式,分辨率过高,网络超时等等。
因此在这些情形下错误处理和恢复非常重要。有时候编程错误也会导致mediaplayer操作错误。
开发者可以设置错误监听器setonerrorlistener(android.media.mediaplayer.onerrorlistener)
。当错误发生时,会调用用户实现的onerrorlistener.onerror()方法。
不管有没有设置监听器,错误发生时mediaplayer会进入error状态。
为了重复使用同一个mediaplayer对象,可以使用reset()
方法把它从error状态恢复到idle状态。
设置错误监听器onerrorlistener是一个好的编程习惯。开发者可以监听到播放引擎的错误通知。
有时候会抛出illegalstateexception异常,比如在错误的状态调用了prepare(), prepareasync()方法,或是setdatasource方法。
设置音源 setdatasource
调用setdatasource(java.io.filedescriptor), 或者 setdatasource(java.lang.string), 或者 setdatasource(android.content.context, android.net.uri), 或者 setdatasource(java.io.filedescriptor, long, long), 或者 setdatasource(android.media.mediadatasource) 可以将mediaplayer的状态从idle转到initialized状态。
如果在idle状态之外的状态调用了setdatasource(),会抛出illegalstateexception异常。
开发者应该留意setdatasource方法抛出的illegalargumentexception和ioexception异常。
播放音频前必须在prepared状态
mediaplayer在开始播放音频前必须处于prepared状态。
mediaplayer有同步和异步2种方式来进入prepared状态。如果是异步的方式,会先转到preparing状态,再转到prepared状态。
当准备完成时,内部的播放引擎会回调用户之前设置的onpreparedlistener的onprepared()方法。
开发者必须注意的是,preparing状态是一个过渡状态(transient state)。
处于prepared状态时,可以通过相对应的方法设置音量,屏幕常亮,播放循环等。
开始播放
播放音频必须调用start()方法。调用start()返回成功后,mediaplayer处于started状态。
可以通过isplaying()来判断当前是否在started状态。
如果开发者设置了onbufferingupdatelistener,android内部播放器会向外传递buffer信息。
如果当前处于started状态,再调用start()方法没有效果。
暂停播放与继续播放
音频可以被暂停播放和继续播放,也可以调整播放的位置。通过pause()方法来暂停音频播放。
成功调用pause()方法后,mediaplayer进入paused状态。
应当注意的是,mediaplayer在started状态与paused状态之间切换是异步的。播放音频流的时候,这个转换过程可能会需要几秒钟。
mediaplayer暂停时,start()方法可以从暂停的位置继续播放。成功调用start方法后会进入started状态。
处于paused状态时,调用pause()方法没有效果。
停止
调用stop()方法让mediaplayer从started, paused, prepared 或 playbackcompleted 状态进入 stopped 状态。
在stopped状态时,必须先调用prepare() 或 prepareasync()进入prepared状态后,才能播放音频。
处于stopped状态时,调用stop()方法没有效果。
调整播放位置
调用seekto(long, int)来调整播放位置。
seekto(long, int)是一个异步方法,虽然它能立刻返回,但实际的位置调整可能会消耗一段时间,特别是在播放音频流的时候。当实际播放位置调整后,内部播放器会回调开发者设置的onseekcomplete.onseekcomplete()。
在prepared, paused 和 playbackcompleted状态中,都可以调用seekto方法。
可以通过getcurrentposition()方法来获取当前播放位置。开发者可以得知当前播放的进度等等。
播放完毕
音频播放完成后,播放完毕。
如果调用setlooping(boolean)为true,mediaplayer会停留在started状态。
如果setlooping为false,内部播放器会调用开发者设置的oncompletion.oncompletion(),并且进入playbackcompleted状态。
处于playbackcompleted状态时,调用start()方法可以从头开始播放音频。
常用监听器
开发者可以设置一些监听器,监听mediaplayer的状态,错误事件等等。开发者应在同一个线程中创建mediaplayer与设置的监听器。
setonpreparedlistener(android.media.mediaplayer.onpreparedlistener)
监听mediaplayer准备完成。一般与prepareasync
配合使用。
setonvideosizechangedlistener(android.media.mediaplayer.onvideosizechangedlistener)
获知video大小或video大小改变时的监听。
setonseekcompletelistener(android.media.mediaplayer.onseekcompletelistener)
监听调整位置完成。
setoncompletionlistener(android.media.mediaplayer.oncompletionlistener)
播放完成。
mediaplayer.setoncompletionlistener(new mediaplayer.oncompletionlistener() { @override public void oncompletion(mediaplayer mediaplayer) { // 当前播放完毕 } });
setonbufferingupdatelistener(android.media.mediaplayer.onbufferingupdatelistener)
监听缓冲进度。在播放网络音频时常用。
缓冲监听器onbufferingupdatelistener
mmediaplayer.prepareasync(); mmediaplayer.setonbufferingupdatelistener(new mediaplayer.onbufferingupdatelistener() { @override public void onbufferingupdate(mediaplayer mp, int percent) { // 例如在这里更新ui } });
setoninfolistener(android.media.mediaplayer.oninfolistener)
监听普通信息或者警告信息。
setonerrorlistener(android.media.mediaplayer.onerrorlistener)
监听错误信息。错误发生时,可以在这里处理错误。
mediaplayer.setonerrorlistener(new mediaplayer.onerrorlistener() { @override public boolean onerror(mediaplayer mediaplayer, int i, int i1) { logutil.e(tag_prefix + " onerr i = " + i + " i1 = " + i1); return true; // 返回true表示在此处理错误,不会回调oncompletion } });
注意onerror的返回值。可以选择自己处理error。
* @return true if the method handled the error, false if it didn't. * returning false, or not having an onerrorlistener at all, will * cause the oncompletionlistener to be called. */ boolean onerror(mediaplayer mp, int what, int extra);
需要的权限
播放网络音频时需要manifest.permission.internet权限。
上一篇: 串口调试助手--Qt
下一篇: 面向切面编程AOP