AndroidMediaPlayer基础简介
本⽂链接:
简单介绍MediaPlayer的基本概念,状态,常⽤的⽅法与。
什么是MediaPlayer
MediaPlayer类可以⽤来播放⾳视频⽂件,或者是⾳频流。开发者可以⽤它来播放本地⾳频,或者是⽹络在线⾳频。
MediaPlayer属于dia包。
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(),
在线播放器dia.AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() 或prepareAsync()⽅法都会抛出错误,如果是新实例化的MediaPlayer,不会回调 Error();但如果是reset后的MediaPlayer,会回调Error()并且转换到Error状态。
如果MediaPlayer对象不再使⽤了,⽴即调⽤release()⽅法,释放内部播放器占⽤的资源。这些资源可能是唯⼀的,⽐如硬件加速组件。如果调⽤release失败,可能会引起⼀连串的MediaPlayer实例失效。当MediaPlayer处于End状态,它就不能再转移到其它状态了。
new⼀个MediaPlayer,处于Idle状态。如果⽤create⽅法创建实例,当创建完成时处于Prepared状态。
发⽣错误
⼀些情形可能会让MediaPlayer操作失败,⽐如不⽀持的⾳视频格式,分辨率过⾼,⽹络超时等等。
因此在这些情形下错误处理和恢复⾮常重要。有时候编程错误也会导致MediaPlayer操作错误。
开发者可以设置错误dia.MediaPlayer.OnErrorListener)。当错误发⽣时,会调⽤⽤户实现的Error()⽅法。
不管有没有设置,错误发⽣时MediaPlayer会进⼊Error状态。
为了重复使⽤同⼀个MediaPlayer对象,可以使⽤reset()⽅法把它从Error状态恢复到Idle状态。
设置错误OnErrorListener是⼀个好的编程习惯。开发者可以监听到播放引擎的错误通知。
有时候会抛出IllegalStateException异常,⽐如在错误的状态调⽤了prepare(), prepareAsync()⽅法,或是setDataSource⽅法。
设置⾳源 setDataSource
调⽤setDataSource(java.io.FileDescriptor), 或者 setDataSource(java.lang.String), 或者 setDataSource(
如果在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)是⼀个异步⽅法,虽然它能⽴刻返回,但实际的位置调整可能会消耗⼀段时间,特别是在播放⾳频流的时候。当实际播放位置调整后,内部播放器会回调开发者设置的SeekComplete()。
在Prepared, Paused 和 PlaybackCompleted状态中,都可以调⽤seekTo⽅法。
可以通过getCurrentPosition()⽅法来获取当前播放位置。开发者可以得知当前播放的进度等等。
播放完毕
⾳频播放完成后,播放完毕。
如果调⽤setLooping(boolean)为true,MediaPlayer会停留在Started状态。
如果setLooping为false,内部播放器会调⽤开发者设置的Completion(),并且进⼊PlaybackCompleted状态。
处于PlaybackCompleted状态时,调⽤start()⽅法可以从头开始播放⾳频。
常⽤
开发者可以设置⼀些,监听MediaPlayer的状态,错误事件等等。开发者应在同⼀个线程中创建MediaPlayer与设置的。dia.MediaPlayer.OnPreparedListener)
监听MediaPlayer准备完成。⼀般与prepareAsync配合使⽤。
dia.MediaPlayer.OnVideoSizeChangedListener)
获知video⼤⼩或video⼤⼩改变时的监听。
dia.MediaPlayer.OnSeekCompleteListener)
监听调整位置完成。
dia.MediaPlayer.OnCompletionListener)
播放完成。
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
// 当前播放完毕
}
});
dia.MediaPlayer.OnBufferingUpdateListener)
监听缓冲进度。在播放⽹络⾳频时常⽤。
缓冲OnBufferingUpdateListener
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// 例如在这⾥更新UI
}
});
dia.MediaPlayer.OnInfoListener)
监听普通信息或者警告信息。
dia.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权限。