Потоковая передача с Android MediaPlayer - отлов ошибок и буферизация - PullRequest
7 голосов
/ 09 января 2010

У меня проблемы с получением MediaPlayer устойчивости при потоковой передаче с HTTP-адреса.

Если я начинаю проигрывать файл, но затем теряю соединение (например, режим полета), MediaPlayer#OnErrorListener генерирует what=1, extra=-17, а вскоре после этого what=-38, extra=0.

Нет никакой документации, которую я могу видеть в API, что это означает, кроме extra "Как правило, зависит от реализации". Я использую HTC Hero (ну, это G2 Touch от T-Mobile Великобритании).

Получают ли другие люди такие же значения, и безопасно ли перехватывать эти значения как означающие, что соединение разорвано?

Как я могу возобновить работу, когда снова появится соединение? (сохранить текущий поиск в настройках и повторять каждые 5 секунд?)

Как узнать, когда устройство решило начать воспроизведение того, что оно буферизировало - есть ли обратный вызов (кроме опроса isPlaying())?

Кроме того, я не совсем уверен, что предоставляет onBufferingUpdate. Я использую 40-минутный подкаст MP3 (64kbps bitrate) - буферизация идет 1%, 2%, 3%. Когда я стремлюсь к 30 минутам, он показывает 75%, затем, когда я возвращаюсь к началу, к 5% - какой смысл в этом обратном вызове, кроме того, что он показывает приблизительно то, что кэшируется?

Наконец - есть ли способ передать то, что передается в MP3?

Ответы [ 4 ]

5 голосов
/ 16 февраля 2011

Взято из Этот похожий вопрос переполнения стека

Я тоже разочарован хуками MEDIA_INFO_BUFFERING_START и MEDIA_INFO_BUFFERING_END ... облом.

Я проверил приложение Pandora и оно не отображает индикатор буферизации. Когда музыка прерывается для буферизация, он просто сидит как будто ничего не произошло и пользовательский интерфейс выглядит это все еще играет. Итак, я пришел к вывод, что если вы используете MediaPlayer, просто невозможно определить, является ли трек временно приостановлено для буферизации.

Однако я заметил, что есть пара констант MediaPlayer, которые может быть полезным: MEDIA_INFO_BUFFERING_START и MEDIA_INFO_BUFFERING_END. Но они доступно только на уровне API 9+ и документы ничего не говорят о их. Я предполагаю, что они могут быть использованы с OnInfoListener.

Я разочарован, но, по крайней мере, могу прекрати крутить мои колеса сейчас и двигайся на что-то еще.

2 голосов
/ 24 ноября 2011

Возможно сделать это

MediaPlayer имеет методы для регистрации OnPreparedListener и OnBufferingUpdateListener

onPrepared будет вызываться, когда игрок достаточно буферизован, чтобы начать играть.

http://developer.android.com/reference/android/media/MediaPlayer.OnPreparedListener.html

onBufferingUpdate будет вызываться для обновления информации о буферизации.

http://developer.android.com/reference/android/media/MediaPlayer.OnBufferingUpdateListener.html

Вам также следует использовать службу подключения для прослушивания сетевых подключений

public boolean hasConnectivity()
{
    ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo info = connectivityManager.getActiveNetworkInfo();

    int netType = info.getType();
    int netSubtype = info.getSubtype();

    if (netType == ConnectivityManager.TYPE_WIFI)
    {
        return info.isConnected();
    }
    else if (netType == ConnectivityManager.TYPE_MOBILE && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS)
    {
        return info.isConnected();
    }

    return false;
}
1 голос
/ 03 февраля 2011

Я думаю, вы должны перечислить потери / выгоды сети. Посмотрите на: Обнаружение восстановления сети 3G или Wifi

0 голосов
/ 22 января 2013

Когда вы ищете или пропускаете, или соединение потеряно, и MediaPlayer продолжает переподключаться к прокси-серверу, вы должны отправить этот ответ со статусом 206 после получения запроса и диапазона (int) от клиента.

String headers += "HTTP/1.1 206 Partial Content\r\n";
headers += "Content-Type: audio/mpeg\r\n";
headers += "Accept-Ranges: bytes\r\n";
headers += "Content-Length: " + (fileSize-range) + "\r\n";
headers += "Content-Range: bytes "+range + "-" + fileSize + "/*\r\n";
headers += "\r\n";

И когда вы получаете запрос от MediaPlayer, который не содержит Range в заголовке HTTP, он запрашивает новый файл потока, в этом случае ваш заголовок ответа должен выглядеть следующим образом:

String headers = "HTTP/1.1 200 OK\r\n";
headers += "Content-Type: audio/mpeg\r\n";
headers += "Accept-Ranges: bytes\r\n";
headers += "Content-Length: " + fileSize + "\r\n";
headers += "\r\n";

Наслаждайтесь!

...