调用MediaPlayer.reset()的IllegalStateException

时间:2011-07-06 15:53:57

标签: android media-player

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

但是,我在调用IllegalStateException时看到reset()抛出:

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)

文档是否不正确?

4 个答案:

答案 0 :(得分:25)

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

文档说明

  

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

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

答案 1 :(得分:8)

我遇到了你的问题,Skyler。

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

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

我进行了实验,但是当MediaPlayer希望处于Preparation状态(使用prepareAsync())时,我试图调用release()时不会引发IllegalStateException。我不保证它不会发生,但我无法实现。我在该实例中看到的是以下日志消息:

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

是的,两个错误消息一个接着一个出现 - 一个小写“错误”,一个大写“错误”,但没有抛出异常。

但是,如果我在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

所以现代墨水的猜测是正确的。 MediaPlayer.reset()在End状态(在调用release()之后发生)抛出IllegalStateException。

就我而言,我发现我在onPause()上调用了release(),但没有在onResume()中再次初始化MediaPlayer。因此,当我调用reset();

时,它处于End状态

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

  

一旦MediaPlayer对象处于End状态,它就不再是   使用过,没有办法把它带回任何其他州。

这意味着您需要重新创建MediaPlayer,从mediaPlayer = new MediaPlayer()或其中一个mediaPlayer.onCreate()方法开始。或者在你调用release()时要小心。

答案 2 :(得分: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关闭应用并第二次启动时,IllegalStateException会在传递reset()功能时发生。

我还在调试时发现了原因。当第一次运行应用时,播放器为空,因此它在onCreate() PlayerActivity.java函数中初始化。但是应用程序关闭后,播放器不会释放到null。因此,当第二次重新打开时,它不会再次初始化。这就是传递IllegalStateException函数时reset()出现的原因。因此,要解决此问题,我必须在关闭应用之前将播放器设置为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();

}

答案 3 :(得分:1)

这有两种可能的发生方式:

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

摆脱媒体播放器的正确顺序是释放它,并将其设置为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();
        }
    });
}