一、
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
状态。
本文来自网易实践者社区,经作者吴思博授权发布。