Android提供的多媒体框架支持播放各种常见媒体类型,可以轻松地将音频、视频和图像集成到应用程序中。
可以使用MediaPlayer api
从存储在应用程序资源(原始资源)中的媒体文件、文件系统中的独立文件或通过网络连接到达的数据流中播放音频或视频。
这张图很好的向我们展示MediaPlayer
各个生命周期,以及处于那种状态如何变换到另一种状态,必须正确的使用每一个状态,以及状态之间的转换,否则就会报IllegalStateException
异常。
下面根据官方文档的翻译以及结合自己的理解
Idle
状态:当使用new()
方法创建一个MediaPlayer
对象或者调用了其reset()
方法时,该MediaPlayer对象处于idle
状态。这两种方法的一个重要差别就是:在这个状态下调用了getDuration()
等方法(相当于调用时机不正确),通过reset()
方法进入idle
状态的话则会触发OnErrorListener.onError()
,并且MediaPlayer会进入Error
状态;如果是新创建的MediaPlayer对象也就是通过new创建,则并不会触发onError()
方法,也不会进入Error
状态。End
状态:通过release()
方法可以进入End状态,只要MediaPlayer对象不再被使用,就应当尽快将其通过release()
方法释放掉,以释放相关的软硬件组件资源,这其中有些资源是只有一份的(相当于临界资源)。如果MediaPlayer对象进入了End
状态,则不会在进入任何其他状态了。Initialized
状态:MediaPlayer
调用setDataSource()
方法就进入Initialized
状态,表示此时要播放的文件已经设置好了。Prepared
状态:初始化完成之后还需要通过调用prepare()
或prepareAsync()
方法,这两个方法一个是同步的一个是异步的,只有进入Prepared
状态,才表明MediaPlayer
到目前为止都没有错误,可以进行文件播放。
prepare
与prepareAsync
区别:主要是他们的执行线程不一样,prepare
运行在调用它的线程中(最常见的UI线程),因此,如果它需要很长时间(缓冲来自互联网的视频等),它将阻塞UI线程,App可能会出现ANR
。PrepareAsync
则运行在后台线程,因此UI线程不会被阻塞,因为它几乎立即返回。但是此时播放器还没有准备好,所以需要设置onPreparedListener
,以便知道何时可以使用MediaPlayer
。Preparing
状态:这个状态比较好理解,主要是和prepareAsync()
配合,如果异步准备完成,会触发OnPreparedListener.onPrepared()
,进而进入Prepared
状态。Started
状态:MediaPlayer
一旦准备好,就可以调用start()
方法,这样MediaPlayer
就处于Started状态,这表明MediaPlayer正在播放文件过程中。可以使用isPlaying()
测试MediaPlayer是否处于了Started状态。如果播放完毕,而又设置了循环播放,则MediaPlayer仍然会处于Started状态,类似的,如果在该状态下MediaPlayer调用了seekTo()
或者start()
方法均可以让MediaPlayer停留在Started状态。Paused
状态:Started
状态下MediaPlayer
调用pause()方法可以暂停MediaPlayer
,从而进入Paused状态,MediaPlayer暂停后再次调用start()则可以继续MediaPlayer的播放,转到Started
状态,暂停状态时可以调用seekTo()
方法,这是不会改变状态的。Stop
状态:Started
或者Paused状态下均可调用stop()
停止MediaPlayer
,而处于Stop状态的MediaPlayer要想重新播放,需要通过prepareAsync()
和prepare()
回到先前的Prepared
状态重新开始才可以。PlaybackCompleted
状态:文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener
的onCompletion()
方法。此时只需要调用start()
方法就可以重新从头播放文件,也可以stop()
停止MediaPlayer,或者也可以seekTo()
来重新定位播放位置。Error
状态:如果由于某种原因MediaPlayer
出现了错误,会触发OnErrorListener.onError()
事件,此时MediaPlayer即进入Error状态,及时捕捉并妥善处理这些错误是很重要的,可以帮助我们及时释放相关的软硬件资源,也可以改善用户体验。通过setOnErrorListener(android.media.MediaPlayer.OnErrorListener)
可以设置该监听器。如果MediaPlayer
进入了Error状态,可以通过调用reset()
来恢复,使得MediaPlayer重新返回到Idle
状态。方法说明
MediaPlayer
构造方法create
创建一个要播放的多媒体getCurrentPosition
得到当前播放位置getDuration
得到文件的时间getVideoHeight
得到视频的高度getVideoWidth
得到视频的宽度isLooping
是否循环播放isPlaying
是否正在播放pause
暂停prepare
准备(同步)prepareAsync
准备(异步)release
释放MediaPlayer对象相关的资源reset
重置MediaPlayer对象为刚刚创建的状态seekTo
指定播放的位置(以毫秒为单位的时间)setAudioStreamType
设置流媒体的类型setDataSource
设置多媒体数据来源(位置)setDisplay
设置用SurfaceHolder来显示多媒体setLooping
设置是否循环播放setOnButteringUpdateListener
网络流媒体的缓冲监听setOnErrorListener
设置错误信息监听setOnVideoSizeChangedListener
视频尺寸监听setScreenOnWhilePlaying
设置是否使用SurfaceHolder
来保持屏幕显示setVolume
设置音量start
开始播放stop
停止播放MediaPlayer
的工作流程是这样的:
MediaPlaer
对象; *setDataSource()
方法来设置音频文件的路径;prepare()
方法使MediaPlayer
进入到准备状态;start
方法就可以播放音频。创建MediaPlaer对象有两种方式
MediaPlayer mp = new MediaPlayer();
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource
当然上面首先得在res文件夹下新建raw文件夹,并放置一个test文件设置播放的文件
MediaPlayer
要播放的文件主要包括3个来源:
MediaPlayer.create(this, R.raw.test);
mp.setDataSource("/sdcard/test.mp3");
mp.setDataSource("http:/xxx.yif.mp3");
MediaPlayer
的setDataSource
一共四个方法:
setDataSource (String path) setDataSource (FileDescriptor fd) setDataSource (Context context, Uri uri) setDataSource (FileDescriptor fd, long offset, long length)