【问题标题】:IllegalStateException calling MediaPlayer.reset()IllegalStateException 调用 MediaPlayer.reset()
【发布时间】:2011-07-06 15:53:57
【问题描述】:

Android MediaPlayer 的文档显示,reset() 调用没有无效状态:http://developer.android.com/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States(无效状态列为 {},或“无”)。

但是,我在调用reset() 时看到了IllegalStateException

java.lang.IllegalStateException
at android.media.MediaPlayer._reset(Native Method)
at android.media.MediaPlayer.reset(MediaPlayer.java:1061)
at com.example.android.player.AsyncPlayer$AsyncHandler.handleMessage(AsyncPlayer.java:654)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.os.HandlerThread.run(HandlerThread.java:60)

文档不正确吗?

【问题讨论】:

  • 嗯,看起来我把MediaPlayer 与另一个主题混淆了。很抱歉造成混乱。 :)

标签: android media-player


【解决方案1】:

很难说没有看到你的代码,但我认为你可能在调用 release() 之后调用了 reset() ?

文档说明

当一个MediaPlayer对象刚被new创建或者reset()被调用后,它处于Idle状态;并且在调用 release() 之后,它处于 End 状态。这两种状态之间是 MediaPlayer 对象的生命周期。

您可能在有效生命周期之外调用了重置。

【讨论】:

  • 是的,在release()之后调用reset()会抛出非法状态异常
【解决方案2】:

我遇到了你的问题,斯凯勒。

你是对的。文档显示 mediaPlayer.reset() 没有无效状态,但这不是文档中的第一个错误。

我注意到 VALID 状态列表没有说“任何”;它列出了除两个之外的每个特定状态:准备和结束。

我进行了实验,但在我尝试调用release() 时无法导致IllegalStateException 被抛出,而MediaPlayer 希望处于PREPARING 状态(使用prepareAsync())。我不能保证它不会发生,但我不能让它发生。我在那个实例中看到的是以下日志消息:

04-11 11:41:54.740: E/MediaPlayer(4930): error (1, -2147483648)
04-11 11:41:54.748: E/MediaPlayer(4930): Error (1,-2147483648)

是的,两条错误消息都出现了,一条紧接着一条——一条带有小写的“error”,一条带有大写的“Error”,但没有抛出异常。

但是,如果我在 release() 之后调用 reset(),则会收到错误消息:

04-11 11:45:05.232: E/AndroidRuntime(5046): FATAL EXCEPTION: main
04-11 11:45:05.232: E/AndroidRuntime(5046): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.helloandroid/com.android.helloandroid.HelloAndroidActivity}: java.lang.RuntimeException: java.lang.IllegalStateException
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1696)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1716)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.ActivityThread.access$1500(ActivityThread.java:124)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:968)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.os.Looper.loop(Looper.java:123)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.ActivityThread.main(ActivityThread.java:3806)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at java.lang.reflect.Method.invokeNative(Native Method)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at java.lang.reflect.Method.invoke(Method.java:507)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at dalvik.system.NativeStart.main(Native Method)
04-11 11:45:05.232: E/AndroidRuntime(5046): Caused by: java.lang.RuntimeException: java.lang.IllegalStateException
04-11 11:45:05.232: E/AndroidRuntime(5046):     at com.android.helloandroid.HelloAndroidActivity.crashMediaPlayer(HelloAndroidActivity.java:423)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at com.android.helloandroid.HelloAndroidActivity.onCreate(HelloAndroidActivity.java:87)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1660)
04-11 11:45:05.232: E/AndroidRuntime(5046):     ... 11 more
04-11 11:45:05.232: E/AndroidRuntime(5046): Caused by: java.lang.IllegalStateException
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.media.MediaPlayer._reset(Native Method)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at android.media.MediaPlayer.reset(MediaPlayer.java:1112)
04-11 11:45:05.232: E/AndroidRuntime(5046):     at com.android.helloandroid.HelloAndroidActivity.crashMediaPlayer(HelloAndroidActivity.java:421)
04-11 11:45:05.232: E/AndroidRuntime(5046):     ... 14 more

所以,The Modern Ink 的猜测是正确的。 MediaPlayer.reset()IllegalStateException 抛出 END 状态(在调用 release() 之后发生)。

在我的例子中,我发现我在 onPause() 上调用了 release(),但没有在 onResume() 中再次初始化 MediaPlayer。因此,当我调用reset() 时,它处于END 状态。

http://developer.android.com/reference/android/media/MediaPlayer.html

一旦 MediaPlayer 对象处于 End 状态,就不能再 使用过,没有办法将其恢复到任何其他状态。

这意味着您需要重新创建 MediaPlayer,从 mediaPlayer = new MediaPlayer()mediaPlayer.onCreate() 方法之一开始。或者当你打电话给release()时要小心。

【讨论】:

    【解决方案3】:

    显然,Android MediaPlayer 的文档对于reset() 没有无效状态是不正确的。以下是我体验时发生的情况:

    在我的PlayerActivity.java 代码中,我将MediaPlayer 设置为静态,以便我可以在家中使用它activity

    public class PlayerActivity extends Activity {
    ....
    
    public static MediaPlayer mp;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Mediaplayer
        if(mp == null) {
            mp = new MediaPlayer();
        }
        ....
    }
    /**
     * Function to play a song
     * @param songIndex - index of song
     * */
    public void  playSong(int songIndex){
        // Play song
        try {
            if(mUpdateTimeTask != null)
                mHandler.removeCallbacks(mUpdateTimeTask);
            mp.reset();
                // the song path is get from internet
        mp.setDataSource(songsList.get(songIndex).get("songPath"));
        mp.prepareAsync();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    ...
    }
    

    在我家activity,我在关闭应用前释放播放器:

    public class TuoiTreAppActivity extends TabActivity {
        ...
    
        @Override
        public void onDestroy(){
            if(PlayerActivity.mp != null) {
            PlayerActivity.mp.release();
            }   
            super.onDestroy();
    
        }
        ...
    
    }
    

    所以,当我第一次启动应用程序并开始播放歌曲时。 reset() 函数运行良好,没有错误。但是当我第二次回击button 关闭应用程序并启动它时,在传递reset() 函数时会出现IllegalStateException

    我在调试的时候也发现了原因。由于第一次运行应用程序,播放器为空,因此在PlayerActivity.javaonCreate() 函数中初始化。但是应用程序关闭后,播放器不会将自己释放到null。所以第二次重新打开时不会再次初始化。这就是传递reset() 函数时出现IllegalStateException 的原因。所以,为了解决这个问题,我必须在关闭应用之前将播放器设置为null

    @Override
    public void onDestroy(){
        if(PlayerActivity.mp != null) {
            PlayerActivity.mp.release();
            // Set the MediaPlayer to null to avoid IlLegalStateException 
                // when call mp.reset() after launching the app again
            PlayerActivity.mp = null;
        }
    
        super.onDestroy();
    
    }
    

    【讨论】:

      【解决方案4】:

      这有两种可能发生:

      1. 如前所述,如果您在release 之后使用reset,则会收到错误消息,这是因为release 将释放系统资源,因此reset 是无效命令。
      2. 如果您尝试在release 之后使用您的mediaPlayer 对象,您也会遇到异常。这是因为您需要重新创建对象并再次请求系统资源。

      删除媒体播放器的正确顺序是释放它,并将其设置为 null。此顺序很重要,否则会导致内存泄漏。

      这是一个简单的例子:

          mediaPlayer.release();
          mediaPlayer = null;
      

      然后当您的用户按下按钮时,例如play,您将不得不重新创建媒体播放器:

      public void createMediaPlayer() {
          mediaPlayer = new MediaPlayer();
          mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
          mediaPlayer.setOnCompletionListener(callbackDelegate);
          mediaPlayer.setOnErrorListener(callbackDelegate);
          mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
              public void onPrepared(MediaPlayer mp) {
                  mediaPlayer.start();
              }
          });
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-16
        • 2012-05-06
        • 1970-01-01
        相关资源
        最近更新 更多