MediaPlayer.prepare выдает исключение IllegalStateException при воспроизведении файла m4a

У меня есть список песен, которые я транслирую с помощью MediaPlayer. Некоторые из песен постоянно работают, а другие постоянно не работают. Я не вижу разницы между этими файлами, и они, похоже, нормально воспроизводятся в itunes и тому подобном.

Когда песни терпят неудачу, возникает исключение IllegalStateException в строке mediaPlayer.prepare(). Выброшенное исключение IllegalStateException не содержит полезной информации (detailMessage имеет значение null, stackState равно null)

Вот мой код

try {
    mediaPlayer.setDataSource(media.url);
    setPlayerState(PlayerState.PREPARING);
    mediaPlayer.prepare();
} catch (Exception e) {
    e.printStackTrace();
    Log.e(TAG, "bad stream");
}

Вот URL файла, который НЕ работает: skdy.bryceb.dev.mediarain.com/song.m4a

Вот тот, который РАБОТАЕТ: skdy.bryceb.dev.mediarain.com/song2.m4a

Есть идеи, почему это работает на одних песнях и не работает на других?


person b-ryce    schedule 15.12.2010    source источник
comment
Этот URL-адрес для одного из файлов, которые вызывают исключение, верно??? Если да, отправьте ссылку на тот, который не вызывает проблем, и я попытаюсь сравнить.   -  person Squonk    schedule 15.12.2010
comment
Вот тот, который работает: skdy.bryceb.dev.mediarain.com/song2.m4a   -  person b-ryce    schedule 15.12.2010
comment
Хм, пока ничего не могу вам сказать. Я могу транслировать оба файла с URL-адреса с помощью Winamp, а также непосредственно в Chrome на моем ПК. Я загрузил оба и отрендерил их в GraphEdit, и они оба выдают идентичные графики и работают без сбоев. В данный момент я между проектами, поэтому поиграю еще немного - если я найду ответ, я свяжусь с вами.   -  person Squonk    schedule 15.12.2010
comment
@MisterSquonk, похоже, это отдельная проблема. Оба файла фактически попадают в исключение. Но первый файл также запускает прослушиватель ошибок медиаплеера с кодом ошибки -38, который сейчас изучается.   -  person b-ryce    schedule 15.12.2010


Ответы (2)


Спасибо, MisterSquonk, я уверен, что этот способ сработает.

В моем конкретном случае, после того как я некоторое время бил головой о стену, я понял, что в некоторых песнях я добирался до буферизованной суммы до того, как состояние проигрывателя становилось подготовленным. Поэтому я добавил проверку, чтобы убедиться, что MediaPlayer находится в состоянии «PREPARED», после чего все заработало отлично:

// Media prepared listener
    mediaPlayer.setOnPreparedListener(
            new MediaPlayer.OnPreparedListener() {
                public void onPrepared(MediaPlayer mp) {
                    setPlayerState(PlayerState.PREPARED);
                }
            });

    // Media buffer listener
    mediaPlayer.setOnBufferingUpdateListener(
            new MediaPlayer.OnBufferingUpdateListener() {
                public void onBufferingUpdate(MediaPlayer mp, int percent) {

                    // Sometimes the song will finish playing before the 100% loaded in has been
                    // dispatched, which result in the song playing again, so check to see if the 
                    // song has completed first
                    if(getPlayerState() == PlayerState.COMPLETED)
                        return;

                    if(getPlayerState() == PlayerState.PAUSED)
                        return;

                    // If the music isn't already playing, and the buffer has been reached
                    if(!mediaPlayer.isPlaying() && percent > PERCENT_BUFFER) {
                        if(getPlayerState() == PlayerState.PREPARED)
                        {
                            mediaPlayer.start();
                            setPlayerState(PlayerState.PLAYING);
                        }
                        //if it isn't prepared, then we'll wait till the next buffering
                        //update
                        return;
                    }
                }
            });
person b-ryce    schedule 15.12.2010

Хорошо, я взломал минимальную реализацию Mediaplayer в приложении/активности «песочницы», которое я всегда оставляю для тестирования.

Я могу ошибаться, но если вы транслируете эти песни по сети, вам нужно добавить префикс http://.

Я пробовал URL-адреса с Winamp и Chrome дословно (без строки префикса протокола), и они работали нормально, хотя, вероятно, оба этих приложения будут использовать некоторую форму интеллекта, чтобы определить, как подключаться / передавать.

Если бы я попробовал это в своем коде mediaPlayer, я бы получил то же исключение, что и вы, но если я добавлю к URL-адресам префикс http://, песни воспроизводятся нормально.

Пример...

// Activity scope
Button button;
CheckBox checkBox;
String url = "";

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //button declared in my activity
    button = (Button)findViewById(R.id.button);
    button.setOnClickListener(this);

    if (!checkBox.isChecked())
        url = getString(R.string.url_song1);
    else
        url = getString(R.string.url_song2);

    mediaPlayer = new MediaPlayer();
}

@Override
public void onClick(View arg0) {
    try {
        Log.i(TAG, "onClick() entered...");
        mediaPlayer.setDataSource(url);
        Log.i(TAG, "Preparing mediaplayer...");
        mediaPlayer.prepare();
        Log.i(TAG, "Starting mediaplayer...");
        mediaPlayer.start();
    } catch (Exception e) {
        e.printStackTrace();
        Log.e(TAG, "bad stream");
    }       
}

Если я скопирую песни на свою SD-карту, они будут воспроизводиться нормально, и если строки URL-адресов в Интернете имеют префикс «http://», они также будут работать.

person Squonk    schedule 15.12.2010