全部产品
云市场

java_lang_IllegalStateException

更新时间:2018-04-19 17:27:07

问题分析:

当一个方法在不合法或不恰当的时间被调用时抛出。

解决方案:

当一个方法在不合法或不恰当的时间被调用时抛出。建议根据状态图检查对象当前状态,更改错误的调用方法时机。

示例一:

  1. java.lang.IllegalStateException
  2. at io.er.yune.MediaPlayer._reset(Native Method)
  3. at io.er.yune.MediaPlayer.reset(MediaPlayer.java:734)
  4. at io.er.yune.widget.VideoView.release(VideoView.java:502)
  5. at io.er.yune.widget.VideoView.access$1500(VideoView.java:69)
  6. at io.er.yune.widget.VideoView$3.surfaceDestroyed(VideoView.java:164)
  7. at android.view.SurfaceView.updateWindow(SurfaceView.java:594)
  8. at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:239)
  9. at android.view.View.dispatchWindowVisibilityChanged(View.java:8170)
  10. at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
  11. at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
  12. at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)
  13. at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1113)

问题分析:

这种异常是由于MediaPlayer的生命周期使用不正确,比如没有调用prepare等方法就先调用isPlaying等方法时,或非合法状态调用prepareAsyn,setDataSource方法时会抛出这种异常。

解决方案:由于MediaPlayer的生命周期使用不正确导致抛出的异常,建议阅读MediaPlayer的状态图,确认不同状态调用正确的函数。

代码示例:

步骤一:初始化操作

// 方案一:通过将音频文件添加到资源结构中的res/raw文件夹中。

  1. MediaPlayer player = MediaPlayer.create(getApplicationContext(), R.raw.music);

// 方案二:以file://开头的本地文件URI

  1. MediaPlayer player = MediaPlayer.create(getApplicationContext(), Uri.parse(“file:///sdcard/music/1.mp3”));

// 方案三:setDataSource方法

  1. MediaPlayer player = new MediaPlayer();
  2. player.setDataSource(“/sdcard/test.3gp”);
  3. 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()方法得到,它可以帮助如音乐播放器的应用程序不断更新播放进度。

  1. private void startPlay() {
  2. player.start();
  3. }
  4. private void stopPlay() {
  5. payer.stop();
  6. }
  7. private void pausePlay() {
  8. player.pause();
  9. }
  10. private void goTo(int pos) {
  11. player.seekTo(pos);
  12. }

步骤三:释放播放资源

当播放到流的末尾,播放就完成了。如果调用了setLooping(boolean)方法开启了循环模式,那么这个MediaPlayer对象会重新进入Started状态。

在播放结束时,应调用MediaPlayer的release()方法,释放播放程序所占用的资源。

  1. private void release() {
  2. if(player != null) {
  3. player.stop();
  4. player.release();
  5. player = null;
  6. }
  7. }

参考文献:

1.https://developer.android.com/reference/android/media/MediaPlayer.html#StateDiagram (MediaPlayer状态图)

2.https://developer.android.com/reference/android/media/MediaPlayer.html (MediaPlayer官方文档)

3.http://www.devdiv.com/Android-MediaPlayer%E7%9A%84%E4%BD%BF%E7%94%A8-thread-130166-1-1.html

4.http://blog.csdn.net/yearafteryear/article/details/8966221