最近刚刚开始工作,公司的产品有播放视频的功能,就着重看了一下视频播放的内容,写了该博客,很多内容均引自于网络资源。表示是菜鸟妹纸一枚。希望可以通过写博客一点儿点儿的进步。
MediaPlayer:
一。 MediaPlayer的生命周期以及各个状态:
1. 当一个MediaPlayer对象刚刚被创建,或者调用了该对象的reset()方法以后,它就处于idle状态,当调用了release()方法以后,它就处于end状态,这两种状态之间即为MediaPlayer对象的生命周期。
- 1.1. 在一个新构建的MediaPlayer对象和一个调用了reset()方法的MediaPlayer对象之间有一个差别:新构建的MediaPlayer在处于idle状态时,如果调用getCurrentPosition(),getDuration(),getVideoHeight(),getVideoWidth(),pause(),start(),stop(),seekTo(),prepare()或者prepareAsync()方法都是编程错误。因为当一个MediaPlayer对象刚被创建的时候。内部的播放引擎和对象的状态都没有改变。在这个时候,调用以上方法,框架将无法回调客户端程序注册的OnErrorListener.onError方法了。但是如果这个MediaPlayer对象调用了reset()方法之后,再调用以上方法,内部的播放引擎就会回调客户端程序注册的OnErrorListener.onError方法,并且将错误的状态传入。
- 1.2. 一旦一个MediaPlayer对象不再被使用,就应该立即调用release()方法来释放在内部的播放引擎中与这个MediaPlayer对象相关联的资源。
- 1.3 使用new操作符创建的MediaPlayer对象处于idle状态,而那些通过重载的create()方法来创建的MediaPlayer对象却不是idle状态,调用该方法创建的MediaPlayer对象已经是prepare状态。
2. 在一般情况下,由于种种原因,一些播放控制操作可能会失败,如不支持的音频、视频格式,缺少隔行扫描的音频,视频,分辨率太高,流超时等原因等。因此,错误报告和恢复在这种情况下是非常重要的。有时,由于编程错误,在处于无效状态的情况下调用了一个播放控制操作可能发生,在所有的这些错误条件下,内部的播放引擎会调用一个由客户端程序员提供的OnErrorListener.onError()方法,客户端程序员可以通过调用MediaPlayer.setOnErrorListener()方法来注册OnErrorListener。
- 2.1 一旦发生错误,MediaPlayer对象会进入到Error状态,为了重用一个处于Error状态的MediaPlayer对象,可以调用reset方法来将这个对象恢复成idle状态。
3. 调用MediaPlayer的setDataSource()方法可以使处于idle状态的MediaPlayer对象迁移到Initialized状态。
- 3.1 setDataSource方法有以下几种形式:setDataSource (String path),setDataSource (FileDescriptor fd),setDataSource (Context context, Uri uri),setDataSource (FileDescriptor fd, long offset, long length)。
- 3.2 如果该MediaPlayer处于其他的状态下,调用setDataSource方法,会抛出IllegalStateException异常。
4. 在开始播放之前,MediaPlayer对象必须要进入到Prepaerd状态。
- 4.1 有两种方法可以使MediaPlayer对象进入到Prepared状态:调用prepare()方法,此方法返回就表示该MediaPlayer对象已经进入到了Prepared状态。要么调用prepareAsync()方法,此方法会使此MediaPlayer进入Preparing状态并返回,而内部的播放引擎会继续未完成的准备工作,当同步版本返回时和异步版本的准备工作完全完成时就会调用客户端程序员提供的OnPreparedListener.onPrepared()监听方法,可以调用MediaPlayer.setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)方法来注册OnPreparedListener。
- 4.2 Preparing是一个中间状态。
- 4.3 在不合适的状态下调用prepare()方法和prepareAsync()方法会抛出IllegalStateException异常,当MediaPlayer对象处于Prepared状态的时候,可以调整音频,视频的属性,例如音量,播放时是否一直亮屏,循环播放等。
5. 要开始播放的时候,调用start()方法,当此方法成功返回时,MediaPlayer的对象处于Started状态,isPlaying()方法可以被调用来测试某个MediaPlayer对象是否在Started状态。
- 5.1 当处于Started状态时,内部播放引擎会调用客户端程序员提供的OnBufferingUpdateListener.onBufferingUpdate()方法,此回调方法允许应用程序追踪流播放的缓冲的状态。
6. 播放可以暂停,停止,以及调整当前播放的位置。当调用pause()方法并返回时,会使MediaPlayer对象进入到Paused状态,注意Started与Paused状态的相互转换在内部的播放引擎中是异步的,所以可能需要一点时间在isPlaying()方法中更新状态。如果在播放流内容,这段时间可能是几秒钟。
- 6.1 调用start()方法会让一个处于Paused状态的MediaPlayer对象从之前暂停的地方恢复播放。当调用start()方法返回的时候,MediaPlayer对象的状态会又变成Started状态。
7. 调用stop()方法会停止播放,并且还会让一个处于Started,Paused,Prepared或PlaybackCompleted状态的MediaPlayer进入Stopped状态。
8. 调用seekTo()方法可以调整播放的位置。
- 8.1 seekTo方法是异步执行的,所以它可以马上返回,但是实际的定位播放操作可能需要一段时间才能够完成,尤其是播放流形式的音频或者视频,当实际的定位播放操作完成以后,内部的播放引擎会调用客户端程序员提供的OnSeekComplete.onSeekComplete()回调方法,可以通过setOnSeekCompleteListener()方法注册。
- 8.2 注意,seekTo()方法也可以在其他状态下调用,比如Prepared,Paused和PlaybackCompleted状态,此外,目前的播放位置,实际可以调用getCurrentPosition()方法得到。它可以帮助应用程序不断的更新播放进度。
9. 当播放到流的末尾,播放完成。
- 9.1 如果调用了setLooping()方法开启了循环模式。那么这个MediaPlayer对象会重新进入到Started状态。
- 9.2 如果没有开启循环模式,那么内部的播放引擎会调用客户端程序员提供的OnCompletion.onCompletion()回调方法,可以通过调用MediaPlayer.setOnCompletionListener()方法来设置,内部的播放引擎一旦调用了OnCompletion.onCompletion()回调方法,说明这个MediaPlayer对象进入了PlayedCompleted状态。
- 9.3 当处于PlaybackCompleted状态的时候,可以再调用start()方法来让这个MediaPlayer对象再进入到Started状态。
二。 MediaPlayer的常用方法:
1. 如何获取到MediaPlayer的实例对象:
- 通过直接new的方式:MediaPlayer mp=new MediaPlayer();
- 使用create的方式:MediaPlayer mp=MediaPlayer.create(this,R.raw.test);使用该种方式不需要调用setDataSource方法设置数据源。
2. 如何设置需要播放的文件:
MediaPlayer要播放的文件主要包括3个来源:
- 用户应用中事先自带的resource资源,例如:MediaPlayer.create(this,R.raw.test);
- 存储在SD卡或其他文件路径下的媒体文件,例如:mp.setDataSource(“/sdcard/test.mp3”);
- 网络上的媒体文件,例如:mp.setDataSource(“http://www.citynorth.cn/music/confucius.mp3”);
3. 对播放器的主要控制方法:
- prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。
- start()是真正启动文件播放的方法,
- pause()和stop()比较简单,起到暂停和停止播放的作用,
- seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。
- release()可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。
- reset()可以使播放器从Error状态中恢复过来,重新会到Idle状态。
4. 设置播放器的监听器:
- setOnPreparedListener:在视频预处理完成后调用。
- setOnCompletionListener:视频播放完成后调用。
- setOnErrorListener:在异步操作调用过程中发生错误时调用,例如视频打开失败。
- setOnBufferingUpdateListener:在网络视频流缓冲变化时调用。
- setOnSeekCompleteListener:在seek操作完成后调用。
- setOnVideoSizeChangedListener:在视频大小已知或更新后调用。
- setOnSubtitleUpdateListener:在字幕需要显示时调用。
- setOnInfoListener:在有警告或错误信息时调用。