IllegalStateException вызывает MediaPlayer.reset()

Документация для Android MediaPlayer показывает, что для вызова reset() нет недопустимых состояний: http://developer.android.com/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States (неверный состояния перечислены как {} или "none." ).

Однако, я видел, как 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)

Неверна ли документация?

Ответ 1

Трудно сказать, не видя ваш код, но я думаю, что вы можете позвонить reset() после вызова release()?

В документации указано

Когда объект MediaPlayer только создается с использованием нового или после вызова reset(), он находится в состоянии ожидания; и после вызова release() он находится в состоянии End. Между этими двумя состояниями находится жизненный цикл объекта MediaPlayer.

Вы можете вызвать reset за пределами действительного жизненного цикла.

Ответ 2

Я столкнулся с вашей проблемой, Skyler.

Вы правы. В документации нет недопустимых состояний для mediaPlayer.reset(), но это не первая неточность в документации.

Я заметил, что список состояний VALID не говорит "Any"; он перечисляет каждое конкретное состояние, кроме двух: "Подготовка и завершение".

Я экспериментировал, но не мог заставить IllegalStateException быть брошенным в моих попытках вызвать release(), в то время как MediaPlayer надеется в состоянии подготовки (с использованием 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)

Да, появляются оба сообщения об ошибках, одно за другим - одно с строчной "ошибкой" и одно с верхним регистром "Ошибка", но исключение Exception не выбрано.

Однако, если я вызываю reset() после release(), я получаю ошибку:

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

Итак, самосовершенствование Ink Ink было правильным. MediaPlayer.reset() выдает исключение IllegalStateException в состоянии End (которое возникает после вызова release()).

В моем случае я обнаружил, что я вызываю release() на onPause(), но ничего не сделал для инициализации MediaPlayer снова в onResume(). Следовательно, он находился в состоянии End, когда я вызывал reset();

Per 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, чтобы закрыть приложение и запустить его во второй раз, IllegalStateException возникает при передаче функции reset().

Я также обнаружил причину при отладке. При первом запуске приложения игрок имеет значение null, поэтому он инициализируется функцией 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();

}