共计 5306 个字符,预计需要花费 14 分钟才能阅读完成。
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()
办法来获取以后播放地位。开发者能够得悉以后播放的进度等等。
Android 8.0
之前应用 seekTo
常常遇到复原播放时地位不准的问题,而且甚至有重头开始播放的景象。这个是因为 seekTo
是回到上一时间点左近的关键帧导致的。
针对这个问题,在最新的 Android 8.0 平台上,曾经有了新的解决方案:seekTo(long msec, @SeekMode int mode)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {mPlayer.seekTo(progress, MediaPlayer.SEEK_CLOSEST);
} else {mPlayer.seekTo(progress);
}
上文的 MediaPlayer.SEEK_CLOSEST
,示意找到给定时刻的最靠近的一帧(frame)。而不必去找关键帧(key frame)。
播放结束
音频播放实现后,播放结束。
如果调用 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);
错误代码 -38
。通常示意状态不对。在谬误的状态执行了谬误的操作。
须要的权限
播放网络音频时须要 Manifest.permission.INTERNET
权限。
【Android 音视频开发系列教程】