MediaPlayer可以用来播放应用的资源文件,文件系统中的文件或网络文件。
MediaPlayer不是线程安全的,它的创建和实例获取应该在同一个线程。如果需要注册callbacks,需要所在线程有一个Looper。
状态图
状态图
播放状态被作为状态机管理,单箭头的线代表同步调用,双箭头的线代表异步调用。
- MediaPlayer对象通过new被创建或调用reset方法之后,处于idle状态,release方法调用之后,它处于end状态。
- 对于新创建的MediaPlayer对象调用getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(android.media.AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() or prepareAsync()是不合法的,但不会触发OnErrorListener.onError(),播放器对象不会发生改变。
对于调用reset之后的对象调用以上方法同样是不合法的,调用会触发触发OnErrorListener.onError(),播放器被转到Error状态。 - 必须保持对MediaPlayer对象的引用实例,避免它被垃圾回收,一旦它被回收会导致任何正在进度的播放停止。
- 使用完之后要调用release方法释放资源,一旦它被释放就不能被使用了。
- 使用new创建的对象处在idle状态,使用#create方法创建的对象处在prepared状态。
- 因为多种原因,播放控制可能会失败,比如不支持的音视频格式,质量不佳的音视频,分辨率太高,流媒体超时等等。在这种情况下报错和恢复是一种比较有效的措施。有时,因为编码错误也会导致播放器报错,比如在无效状态下触发控制操作。基于这种情况,我们可以通过 setOnErrorListener注册OnErrorListener。
- 一旦错误发生,MediaPlayer进入Error状态,即使没有注册Error 监听。
- 为了重用一个MediaPlayer对象,把它从Error状态恢复,可以调用reset方法重置它的状态为idle。
- 建议注册 OnErrorListener
- 在无效的状态调用prepare(), prepareAsync()或者setDataSource会抛出IllegalStateException。
- 调用setDataSource方法会把MediaPlayer对象从idle状态转换到 Initialized状态。
- 在其他状态调用setDataSource会抛出IllegalStateException。
- setDataSource可能会抛出IllegalArgumentException 和 IOException
- MediaPlayer对象会在进入started之前,首先进入prepared状态。
- 有两种方式可以转换到prepared状态,同步和异步的方式。
同步的方式prepare()会把MediaPlayer对象转换为prepared状态,等方法返回之后。
异步的方式 prepareAsync()会首先把MediaPlayer对象转换为preparing状态,内部播放引擎会继续工作直到准备工作完成。
如果我们设置了 OnPreparedListener,进入prepared状态会回调 onPrepared()方法。 - preparing是一种短暂的中间状态。我们没有定义在preparing状态调用任何具有副作用的方法的行为。
- 在任何其他状态调用 prepare() or prepareAsync()会抛出 IllegalStateException。
- 当播放器处于prepared状态,我们可以设置audio/sound volume,screenOnWhilePlaying, looping。
- 调用start方法来开始播放视频,开始播放视频之后,MediaPlayer处于started状态,我们可以调用isPlaying()方法来判断视频是否播放。
- 在started状态,如果我们设置了OnBufferingUpdateListener,播放流式数据时会通过 OnBufferingUpdateListener.onBufferingUpdate()回调buffering状态。
- 如果MediaPlayer已经处于started状态,调用start方法没有任何作用。
- 播放可以被暂停和停止,我们通过调用pause方法暂停一个视频,使MediaPlayer处于paused状态。播放和暂停之前的转换在播放引擎中是异步执行的,在状态更新之前调用 isPlaying可能需要花费一些时间,对于流式内容可能需要几秒钟。
- 调用start方法可以把MediaPlayer从paused状态更新为started状态。
- 对于已经处于paused状态的MediaPlayer调用pause方法没有任何作用。
- 调用stop方法停止播放,stop可以使started,paused,prepared或 PlaybackCompleted的MediaPlayer进入stopped状态。
- 一旦进入stopped状态,播放不能被启动直到prepare或prepareAsync方法被调用来是MediaPlayer重新进入prepared状态。
- 对于已经处在stopped状态的MediaPlayer调用stop方法没有任何作用。
- 可以通过调用seekTo调整播放进度。
- seekTo方法属于异步方法,实际的seek操作可能会花费一段时间结束,尤其对于流式内容。当seek结束之后,播放引擎会回调 我们之前设置的 OnSeekComplete.onSeekComplete()方法。
- 在prepared,paused或 PlaybackCompleted状态,seekTo也可以被调用。
- 调用 getCurrentPosition() 可以获取当前的进度。
- 播放完成
- 如果我们通过setLooping(boolean)设置循环模式为true,MediaPlayer将会保持在started状态。
- 如果循环模式被设置为false,则播放完成之后播放引擎会触发我们之前设置的 OnCompletionListener的 OnCompletion.onCompletion() 方法,并且MediaPlayer对象现在处在 PlaybackCompleted状态。
- 当处在PlaybackCompleted状态,调用start方法会从头开始播放音视频文件。
当播放网络内容时,需要申请 Manifest.permission.INTERNET权限。
参考:
https://developer.android.google.cn/reference/android/media/MediaPlayer
网友评论