添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
愤怒的键盘  ·  oracle三个连接配置文件 ...·  21 小时前    · 
多情的圣诞树  ·  透传 Attributes | Vue.js·  1 月前    · 
高大的丝瓜  ·  Android ...·  1 月前    · 
好帅的砖头  ·  TemplateDoesNotExist ...·  2 月前    · 
有胆有识的勺子  ·  FATAL: Ident ...·  5 月前    · 
打酱油的香槟  ·  Help And Training ...·  7 月前    · 

播放器之MediaPlayer详解与总结

达芬奇密码 2018-07-23 09:31

一、 MediaPlayer 详解

二、常用方法

1 、使用进度条:

2 prepare 方法和 prepareAsync 方法的区别

3 、与 MediaPlayer 有关的事件监听器:

4 Mediaplayer onCompletion 的异常调用问题解决

三、 可优化方向

一、 MediaPlayer 详解:

Audioplayer sdk 播放器 1.0 版本使用的是 Android 系统音频 / 视频 MediaPlayer 类。 MediaPlayer 类公共方法 蓝色(重要方法)

1 static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder)

指定从资源 ID 对应的资源文件中来装载音乐文件,同时指定了 SurfaceHolder 对象并返回 MediaPlyaer 对象。

2 static MediaPlayer create(Context context, int resid) 指定从资源 ID 对应的资源文件中来装载音乐文件,并返回新创建的 MediaPlyaer 对象。

3 static MediaPlayer create(Context context, Uri uri) 从指定 Uri 装在音频文件,并返回新创建的 MediaPlayer 对象。

4 int getCurrentPosition() 获取当前播放的位置。

5 int getDuration() 获取音频的时长。

6 int getVideoHeight() 获取视频的高度。

7 int getVideoWidth() 获取视频的宽度。

8 boolean isLooping() 判断 MediaPlayer 是否正在循环播放。

9 boolean isPlaying() 判断 MediaPlayer 是否正在播放。

10 void pause() 暂停播放。

11 void prepare() 准备播放(装载音频),调用此方法会使 MediaPlayer 进入 Prepared 状态。

12 void prepareAsync() 准备播放异步音频。

13 void release() 释放媒体资源。

14 void reset() 重置 MediaPlayer 进入未初始化状态。

15 void seekTo(int msec) 寻找指定的时间位置。

16 void setAudioStreamType(int streamtype) 设置音频流的类型。

17 void setDataSource(String path) 指定装载 path 路径所代表的文件。

18 void setDataSource(Context context, Uri uri, Map<String, String headers)

指定装载 uri 所代表的文件。

19 void setDataSource(Context context, Uri uri) 指定装载 uri 所代表的文件。

20 void setDataSource(FileDescriptor fd, long offset, long length) 指定装载 fd 所代表的文件中从 offset 开始长度为 length 的文件内容。

21 void setDataSource(FileDescriptor fd) 指定装载 fd 所代表的文件。

22 void setDisplay(SurfaceHolder sh) 设置显示方式。

23 void setLooping(boolean looping) 设置是否循环播放。

24 void setNextMediaPlayer(MediaPlayer next) 设置当前流媒体播放完毕 , 下一个播放的 MediaPlayer

25 void setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener) 注册一个回调函数 , 在网络视频流缓冲变化时调用。

26 void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) Media Player 的播放完成事件绑定事件监听器。

27 void setOnErrorListener(MediaPlayer.OnErrorListener listener)

MediaPlayer 的播放错误事件绑定事件监听器。

28 void setOnPreparedListener(MediaPlayer.OnPreparedListener listener)

MediaPlayer 调用 prepare() 方法时触发该监听器。

29 void setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener) MediaPlayer 调用 seek() 方法时触发该监听器。

30 setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener) 注册一个用于监听视频大小改变的监听器。

31 void setScreenOnWhilePlaying(boolean screenOn) 置是否使用 SurfaceHolder 来显示。

32 void setSurface(Surface surface) 设置 Surface

33 void setVideoScalingMode(int mode) 设置视频缩放的模式。

34 void setVolume(float leftVolume, float rightVolume) 设置播放器的音量。

35 void setWakeMode(Context context, int mode) MediaPlayer 设置低级电源管理行为。 .

36 void start() 开始或恢复播放。

37 void stop() 停止播放

二、常用方法

1 、使用进度条:

歌单中每一首歌曲开始播放前,都会回调此接口,进度条用 SeekBar 实现,同时用户也可以利用 SeekBar 的滑块来控制音乐的播放。

SeekBar 需要使用的一些方法:

1 setProgress int value ):设置滑块的位置方法为。

2 setMax(int value) :设置进度条的最大长度。

3 setOnSeekBarChangeListener(OnSeekBarChangeListener l) :设置 SeekBar 的进度改变事件。

MusicPlayer 需要使用的一些方法 :

1 getDuration() :获得音乐长度为。

2 getCurrentPosition() :获得现在播放的位置。

3 seekTo(int msec) :调用 seekTo() 方法可以调整播放的位置。( seekTo(int) 方法是异步执行的,所以它可以马上返回,但是实际的定位播放操作可能需要一段时间才能完成,尤其是播放流形式的音频 / 视频。当实际的定位播放操作完成之后,内部的播放引擎会调用客户端程序员提供的 OnSeekComplete.onSeekComplete() 回调方法。可以通过 setOnSeekCompleteListener(OnSeekCompleteListener) 方法注册。 seekTo(int) 方法也可以在其它状态下调用,比如 Prepared Paused PlaybackCompleted 状态。此外,目前的播放位置,实际可以调用 getCurrentPosition() 方法得到,它可以帮助如音乐播放器的应用程序不断更新播放进度。)

2 prepare 方法和 prepareAsync 方法的区别

prepare 方法是将资源同步缓存到内存中,一般加载本地较小的资源可以用这个,如果是较大的资源或者网络资源建议使用 prepareAsync 方法,异步加载。但如果想让资源启动,即 start() 起来 , 因为在异步中 , 如果不设置监听直接 start 的话,是拿不到这个资源 , 如果让线程睡眠一段时间,则可以取得资源 , 因为这个时候,异步线程已经取得资源,但不可能使用线程睡眠的方式来获取资源,所以就需要设置监听事件 setOnPreparedListener(); 来通知 MediaPlayer 资源已经获取到了 , 然后实现 onPrepared(MediaPlayer mp) 方法 . 在里面启动 MediaPlayer

3 、与 MediaPlayer 有关的事件监听器:

MediaPlayer 提供了一些绑定事件监听器的方法,用于监听 MediaPlayer 播放过程中所发生的特定事件,绑定事件监听器的方法如下。

26 void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) Media Player 的播放完成事件绑定事件监听器。

27 void setOnErrorListener(MediaPlayer.OnErrorListener listener)

MediaPlayer 的播放错误事件绑定事件监听器。

28 void setOnPreparedListener(MediaPlayer.OnPreparedListener listener)

MediaPlayer 调用 prepare() 方法时触发该监听器。

29 void setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener) MediaPlayer 调用 seek() 方法时触发该监听器。

因此可以在创建一个 MediaPlayer 对象之后,通过为该 MediaPlayer 绑定监听器来监听相应的事件

4 Mediaplayer onCompletion 的异常调用问题解决

onCompletion() 正常情况下是在一首歌曲播放完之后会得到调用,但是现在发现有时候会异常调用,找了一些资料,发现如果在 mediaplayer setDataSource 之前就调用了类似 getDuration() 的方法就会出错, onCompletion() 就会被调用。 (例如: 通过新开一个线程,不断地通过 getDuration() 来获取歌曲进度的,但是当我们快速点击 list 上面的歌曲的时候,歌曲在切换的瞬间 ( 即当 mediaplayer reset 之后, setDataSource 之前 ) ,那个线程来不及反应还没停止继续在 getDuration() ,所以会有很大的几率出现 onCompletion() 被异常调用的情况。)

解决方法是: onCompletion() 里面进行判断,如果当前状态是播放或者暂停情况下, onCompletion() 被调用,就不更 View! 因为在点击 list 上的歌曲之前只有 2 种可能性,要么播放 started ,要么 paused ,其他状态点击 list 上的歌曲不会出现异常调用 onCompletion() 的可能,而我们正常情况下一首歌播放完切换下一首歌的时候 mediaplayer 的状态不会是 started 或者 paused, 那么现在问题又来了,怎么获取当前 mediaplayer 状态, mediaplayer 本身是没有这个方法的,只有 isPlaying 判断是否在播放,对于我们呢没有用,所以我们自己需要加一个状态码,在每次 mediaplayer 状态切换的时候对这个状态码进行修改。

1 End 状态:通过 release() 方法可以进入 End 状态,只要 MediaPlayer 对象不再被使用,就应当尽快将其通过 release() 方法释放掉,以释放相关的软硬件组件资源,这其中有些资源是只有一份的(相当于临界资源)。如果 MediaPlayer 对象进入了 End 状态,则不会再进入任何其他状态了。

2 Initialized 状态:这个状态比较简单, MediaPlayer 调用 setDataSource() 方法就进入 Initialized 状态,表示此时要播放的文件已经设置好了。

提示:若当此 MediaPlayer 处于其它的状态下,调用 setDataSource() 方法,会抛出 IllegalStateException 异常。

3 Prepared 状态:初始化完成之后还需要通过调用 prepare() prepareAsync() 方法,这两个方法一个是同步的一个是异步的,只有进入 Prepared 状态,才表明 MediaPlayer 到目前为止都没有错误,可以进行文件播放。

提示:在不合适的状态下调用 prepare() prepareAsync() 方法会抛出 IllegalStateException 异常。当 MediaPlayer 对象处于 Prepared 状态的时候,可以调整音频 / 视频的属性,如音量,播放时是否一直亮屏,循环播放等。

4 Preparing 状态:这个状态比较好理解,主要是和 prepareAsync() 配合,如果异步准备完成,会触发 OnPreparedListener.onPrepared() ,进而进入 Prepared 状态。

5 Started 状态:显然, MediaPlayer 一旦准备好,就可以调用 start() 方法,这样 MediaPlayer 就处于 Started 状态,这表明 MediaPlayer 正在播放文件过程中。可以使用 isPlaying() 测试 MediaPlayer 是否处于了 Started 状态。如果播放完毕,而又设置了循环播放,则 MediaPlayer 仍然会处于 Started 状态,类似的,如果在该状态下 MediaPlayer 调用了 seekTo() 或者 start() 方法均可以让 MediaPlayer 停留在 Started 状态。

6 Paused 状态: Started 状态下 MediaPlayer 调用 pause() 方法可以暂停 MediaPlayer ,从而进入 Paused 状态, MediaPlayer 暂停后再次调用 start() 则可以继续 MediaPlayer 的播放,转到 Started 状态,暂停状态时可以调用 seekTo() 方法,这是不会改变状态的。

7 Stop 状态: Started 或者 Paused 状态下均可调用 stop() 停止 MediaPlayer ,而处于 Stop 状态的 MediaPlayer 要想重新播放,需要通过 prepareAsync() prepare() 回到先前的 Prepared 状态重新开始才可以。

8 PlaybackCompleted 状态:文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发 OnCompletionListener onCompletion() 方法。此时可以调用 start() 方法重新从头播放文件,也可以 stop() 停止 MediaPlayer ,或者也可以 seekTo() 来重新定位播放位置。

9 Error 状态:在一般情况下,由于种种原因一些播放控制操作可能会失败,如不支持的音频 / 视频格式,缺少隔行扫描的音频 / 视频,分辨率太高,流超时等原因,等等会触发会触发 OnErrorListener.onError() 事件,此时 MediaPlayer 会进入 Error 状态,及时捕捉并妥善处理这些错误是很重要的,可以帮助我们及时释放相关的软硬件资源,也可以改善用户体验。

开发者可以通过 setOnErrorListener(android.media.MediaPlayer.OnErrorListener 设置监听器来监听 MediaPlayer 是否进入 Error 状态。如果 MediaPlayer 进入了 Error 状态,可以通过调用 reset() 来恢复,使得 MediaPlayer 重新返回到 Idle 状态。

本文来自网易实践者社区,经作者吴思博授权发布。