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