IllegalStateException вызывая MediaPlayer.reset () - PullRequest
17 голосов
/ 06 июля 2011

Документация для 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)

Документация неверна?

Ответы [ 4 ]

25 голосов
/ 07 января 2012

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

В документации говорится

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

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

8 голосов
/ 11 апреля 2012

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

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

Что я заметил, так это то, что в списке ДЕЙСТВИТЕЛЬНЫХ состояний не написано «Любой»; в нем перечислены все конкретные состояния, кроме двух: Подготовка и Конец.

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

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

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

Так что предположение Современных Чернил было верным. MediaPlayer.reset () создает исключение IllegalStateException в состоянии «Конец» (которое возникает после вызова release ()).

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

За http://developer.android.com/reference/android/media/MediaPlayer.html,

Как только объект MediaPlayer находится в состоянии End, он больше не может быть используется, и нет никакого способа вернуть его в любое другое состояние.

Это означает, что вам нужно заново создать MediaPlayer, начиная с mediaPlayer = new MediaPlayer () или одного из методов mediaPlayer.onCreate (). Или будьте осторожны при вызове release ().

3 голосов
/ 21 января 2013

Очевидно, что документация для 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.

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

}
1 голос
/ 02 сентября 2018

Это может произойти двумя способами:

  1. Как упоминалось ранее, если вы reset после release, вы получите сообщение об ошибке, потому что release будет распоряжаться системными ресурсами и, следовательно, reset является недопустимой командой.
  2. Если вы попытаетесь использовать объект mediaPlayer после release, вы также получите исключение. Это потому, что вам нужно заново создать объект и снова запросить системные ресурсы.

Правильный порядок избавления от вашего медиаплеера - освободить его и установить в ноль. Этот порядок важен , так как в противном случае у вас будут утечки памяти.

Вот краткий пример:

    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();
        }
    });
}
...