Android mediaPlayer – есть ли метод isPrepared() или getStatus()?

У меня проблемы с Android MediaPlayer. Кажется, что в нем отсутствуют важные функции, в основном способ получить текущий статус MediaPlayer или узнать, подготовлен ли он. Я знаю, что есть подготовленный слушатель, но MediaPlayer длится дольше, чем Activity, поэтому, когда Playing Activity возобновляется, было бы неплохо получить текущее состояние плеера, независимо от того, пытается ли он загрузить медиафайл, загружен ли медиафайл и т. д. Я что-то упускаю, или я должен сам отслеживать состояния игроков?

Другая функциональность, которая была бы хороша, это onPlayStateChanged() - в настоящее время мне приходится отслеживать состояние воспроизведения вручную. Я делаю это неправильно?


person StackOverflowed    schedule 09.08.2012    source источник


Ответы (6)


Надеюсь, еще не поздно для ответа. В классе MediaPlayer нет таких вещей, как метод isPrepared() или getStatus(), и вы должны сами следить за его состоянием. Впрочем, это не так сложно.

Класс MediaPlayer имеет хорошую диаграмму состояний, которая действительно помогает. Вы должны реализовать свой сервис на основе этой диаграммы. Кроме того, если вы всегда управляете объектом MediaPlayer из одного и того же потока, легко отслеживать его состояние, поэтому я рекомендую вам это делать. Метод prepareAsync() — это единственный асинхронный метод, о котором вам нужно позаботиться, но вы можете сохранить логическое значение, указывающее, что проигрыватель готовится, что будет «истинным» от вызова prepareAsync() до тех пор, пока onPrepared() не будет называется. В любом случае, вы всегда можете реализовать onError и поймать IllegalStateException, чтобы избежать сбоев, если вы случайно вызовете какой-либо метод из недопустимого состояния.

Тем не менее руководство по воспроизведению мультимедиа мне очень помогло.

person Alex Machado    schedule 11.10.2013
comment
Отметить это как принятый ответ. Печальная реальность заключается в том, что Android для воспроизведения/потребления мультимедиа действительно не хватает, и даже базовые функции, такие как поиск состояния, отсутствуют. Лучший способ обойти это — написать оболочку вокруг объекта MediaPlayer и сохранить состояние самостоятельно. - person StackOverflowed; 05.04.2014
comment
Просто сам столкнулся с этой проблемой. Такая нелепая оплошность, учитывая, насколько чувствительны его методы к текущему состоянию. - person Jarrod Smith; 13.08.2015
comment
По крайней мере, они могли бы сделать Без операции вместо того, чтобы бросать брутальное IllegalStateException в конечный автомат - person Jemshit Iskenderov; 04.07.2019

Мне нужно было видеть статус во время отладки, чтобы устранить проблему, поэтому я просто разместил этот код где-то после того, как узнал, что MediaPlayer был подготовлен:

try {
    this.audioPlayer.prepare();
} catch (Exception e) {
}

Это выводит на консоль ошибку типа «E/MediaPlayer﹕ prepareAsync вызывается в состоянии 32».

Теперь, если бы я мог просто найти место, где перечислены все коды состояния...

person arlomedia    schedule 17.08.2014
comment
Этот код может вызвать исключение, если он находится в неправильном состоянии; но он предназначен для фактического запуска нового состояния, что в большинстве случаев ЭТО НЕ то, что вы хотите. - person Gogu CelMare; 07.09.2020
comment
Согласно документации MediaPlayer (developer.android.com/reference/android/media/), prepare() выдает исключение, если вызывается в любом состоянии, кроме состояния Initialized. Поэтому мое предложение использовать это после того, как вы знаете, что MediaPlayer подготовлен, должно работать надежно. - person arlomedia; 07.09.2020

Я нашел кое-что, что может быть полезно для вас и других. В классе MediaPlayer есть функция setOnPreparedListener(), которая позволяет запускать фрагмент кода, когда MediaPlayer подготовлен.

Кроме того, если вы хотите убедиться, что ваш медиафайл загружен, вы можете использовать функцию getDuration(). Этот код возвращает продолжительность в миллисекундах, если продолжительность недоступна, он возвращает -1. Ниже приведен код:

yourMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        if(yourMediaPlayer.getDuration() != -1){
            //your code when when something is loading
        }
    }
}
person parsa sadredini    schedule 14.03.2020

Класса getState класса MediaPlayer нет, но внутри у него есть состояние, как объяснил alex.magellan. Вызов методов в «недопустимых состояниях» приводит к исключению.

Чтобы избежать этого, я создал класс StateMachine с MediaPlayerWrapper. Таким образом, вместо прямого вызова MediaPlayer используется MediaPlayerWrapper, который внутренне обновляет StateMachine и предоставляет метод getState().

Реализации классов StateMachine и Wrapper можно найти здесь.

person Jemshit Iskenderov    schedule 24.07.2019

Я не думаю, что есть способ сделать это через класс MediaPlayer.

Проще всего сделать глобальную переменную, которая устанавливается в значение true при создании и сбросе. При выпуске устанавливается значение false.

boolean playerAvailable = true;

mediaPlayer = MediaPlayer.create(myContext, soundId); // ready to play

playerAvailable = true;

....

mediaPlayer.reset();   // ready to play again

playerAvailable = true;

....

mediaPlayer.release(); // can't be played until release.

playerAvailable = false;
person Deskcode Solution    schedule 07.11.2019
comment
Это безумие, что я задал этот вопрос 7 лет назад, и команда Android до сих пор не решила его. - person StackOverflowed; 13.11.2019

вы можете найти обходной путь для этого, имея предопределенную логическую переменную и установив для нее значение true при вызове обратного вызова onPrepared() и установив для нее значение false при запуске MediaPlayer. Например:

public boolean mpPrepared = false;

mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        mpPrepared = true;
    }
});

mp.start();
mpPrepared = false;
person harveyhans    schedule 23.02.2021