音乐播放器---解决使用MediaPlayer开发时抛IllegalStateException异常的办法
在使用MediaPlayer开发音乐播放器时,最常遇见的应该是IllegalStateException异常了。首先要明确IllegalStateException这个异常是指“非法的状态”。Android的mediaplayer API中用到了JNI,也就是我们的java代码是要调用native的C++方法的(mediaplayer是用c++实现的),而这里之所以出现这个异常,就是因为我们java里面的mediaplayer对象的状态和native的对象状态发生了不一致。
如下是MediaPlayService.java中实现播放的代码,报异常是在mediaPlayer.setDataSource(path)这一行。
public void play(String path){
//Log.d(TAG,"play file path : " + path);
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
try {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//reset()后,mediaplayer 处于IDLE状态
mediaPlayer.reset();
mediaPlayer.setDataSource(path);
mediaPlayer.prepareAsync();
} catch (Exception e) {
//Log.d(TAG, "play IllegalStateException----");
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 装载完毕回调
mediaPlayer.start();
//用于更新歌曲名称,歌唱者信息
Intent intent = new Intent();
intent.setAction(START_ACTION);
sendBroadcast(intent);
new Thread(){
@Override
public void run() {
while (mediaPlayer.isPlaying()){
// 将SeekBar位置设置到当前播放位置
Message msg = Message.obtain();
Bundle data = new Bundle();
msg.what = 0;
//获取歌曲的时长,单位是毫秒
int length = mediaPlayer.getDuration();
//获取歌曲当前的播放进度
int currentLength = mediaPlayer.getCurrentPosition();
data.putInt("length", length);
data.putInt("currentLength", currentLength);
msg.setData(data);
try {
// 每1秒更新一次位置
MusicItemActivity.handler.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
});
}
在分析解决该异常之前,需要对mediaplayer的各状态有所了解,如下图所示。详细的介绍可以参考http://blog.****.net/hejjunlin/article/details/52349221
在mediaPlayer = new MediaPlayer()后,mediaPlayer处于Idle状态,通过setDataSource,之后可以正常播放音乐。此时如果点击暂停按钮,在点击下一首播放(该条件是我自己测试的时候出现的)就会报出IllegalStateException异常。参考该图可以发现原因,播放时处于Started状态,通过调用setDataSource加载播放路径时mediaPlayer状态不对,需要通过调用reset()使mediaPlayer重新处于Idle状态即可,如代码中注释的那样。