问题分析
当一个方法在不合法或不恰当的时间被调用时抛出。
解决方案
当一个方法在不合法或不恰当的时间被调用时抛出。建议根据状态图检查对象当前状态,更改错误的调用方法时机。
示例一
java.lang.IllegalStateException
at io.er.yune.MediaPlayer._reset(NativeMethod)
at io.er.yune.MediaPlayer.reset(MediaPlayer.java:734)
at io.er.yune.widget.VideoView.release(VideoView.java:502)
at io.er.yune.widget.VideoView.access$1500(VideoView.java:69)
at io.er.yune.widget.VideoView$3.surfaceDestroyed(VideoView.java:164)
at android.view.SurfaceView.updateWindow(SurfaceView.java:594)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:239)
at android.view.View.dispatchWindowVisibilityChanged(View.java:8170)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
问题分析:
这种异常是由于MediaPlayer的生命周期使用不正确,比如没有调用prepare等方法就先调用isPlaying等方法时,或非合法状态调用prepareAsyn,setDataSource方法时会抛出这种异常。
解决方案:由于MediaPlayer的生命周期使用不正确导致抛出的异常,建议阅读MediaPlayer的状态图,确认不同状态调用正确的函数。
代码示例
步骤一:初始化操作
// 方案一:通过将音频文件添加到资源结构中的res/raw文件夹中。
MediaPlayer player =MediaPlayer.create(getApplicationContext(), R.raw.music);
// 方案二:以file://开头的本地文件URI
MediaPlayer player =MediaPlayer.create(getApplicationContext(),Uri.parse(“file:///sdcard/music/1.mp3”));
// 方案三:setDataSource方法
MediaPlayer player =newMediaPlayer();
player.setDataSource(“/sdcard/test.3gp”);
player.prepare();
步骤二:播放控制
关键状态及函数说明:
准备好MediaPlayer后,想要开始播放,必须调用start()
方法。当此方法成功返回时,MediaPlayer的对象处于Started状态。
isPlaying()
方法可以被调用来测试某个MediaPlayer对象是否在Started状态。而对一个已经处于Started状态的MediaPlayer对象调用start()
方法没有影响。
start()
方法调用之后调用pause()
方法并返回时,播放可以被暂停会使MediaPlayer对象进入Paused状态。调用start()
方法会让一个处于Paused状态的MediaPlayer对象从之前暂停的地方恢复播放。当调用start()
方法返回的时候,MediaPlayer对象的状态会又变成Started状态。在Started与Paused状态的相互转换在内部的播放引擎中是异步的。所以可能需要一点时间在isPlaying()
方法中更新状态,若在播放流内容,这段时间可能会有几秒钟。
调用stop()
方法会停止播放,并且还会让一个处于Started、Paused、Prepared或PlaybackCompleted状态的MediaPlayer进入Stopped状态。
调用seekTo()
方法可以调整播放的位置。seekTo(int)
方法是异步执行的,所以它可以马上返回,但是实际的定位播放操作可能需要一段时间才能完成,尤其是播放流形式的音频/视频。当实际的定位播放操作完成之后,内部的播放引擎会调用客户端程序员提供的OnSeekComplete.onSeekComplete()
回调方法。可以通过setOnSeekCompleteListener(OnSeekCompleteListener)
方法注册。seekTo(int)
方法也可以在其它状态下调用,比如Prepared、Paused和PlaybackCompleted状态。
播放位置可以调用getCurrentPosition()
方法得到,它可以帮助如音乐播放器的应用程序不断更新播放进度。
private void startPlay() {
player.start();
}
private void stopPlay() {
payer.stop();
}
private void pausePlay() {
player.pause();
}
private void goTo(int pos) {
player.seekTo(pos);
}
步骤三:释放播放资源
当播放到流的末尾,播放就完成了。如果调用了setLooping(boolean)
方法开启了循环模式,那么这个MediaPlayer对象会重新进入Started状态。
在播放结束时,应调用MediaPlayer
的release()
方法,释放播放程序所占用的资源。
private void release() {
if(player != null) {
player.stop();
player.release();
player = null;
}
}