audio скачать - Android-Размер буфера MediaPlayer в ICS 4.0




music best (3)

Для меня было решение использовать MediaCodec с AudioTrack, я нашел все, что мне нужно знать здесь:

Это может быть решение: http://www.piterwilson.com/blog/2014/03/15/mediacodec-mediaextractor-and-audiotrack-to-the-rescue/

Я использую сокет как прокси для MediaPlayer, поэтому я могу загружать и расшифровывать mp3-аудио, прежде чем записывать его в сокет. Это похоже на пример, показанный в новостном приложении NPR, но я использую его для всех Android версии 2.1 - 4 атм.

Код NPR StreamProxy - http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java

Моя проблема в том, что воспроизведение выполняется быстро для 2.1 - 2.3, но в Android 4.0 ICS MediaPlayer буферизует слишком много данных перед запуском onPrepared прослушивателя.

Пример количества данных, записанных в Socket OutputStream до onPrepared ():

На SGS2 с 2.3.4 - onPrepared () после ~ 133920 байт

На Nexus S с 4.0.4 - onPrepared () после ~ 961930 байт

Это также происходит на Galaxy Nexus.

Как ни странно, эмулятор 4.0 не буферизует столько данных, сколько 4.0. Кто-нибудь сталкивается с аналогичной проблемой с MediaPlayer в ICS?

РЕДАКТИРОВАТЬ

Вот как прокси пишет в сокет. В этом примере это из CipherInputStream, загруженного из файла, но то же самое происходит, когда он загружается из HttpResponse.

final Socket client = (setup above)

// encrypted file input stream
final CipherInputStream inputStream = getInputStream(file);

// setup the socket output stream
final OutputStream output =  client.getOutputStream();

// Writing the header
final String httpHeader = buildHttpHeader(file.length());
final byte[] buffer = httpHeader.getBytes("UTF-8");
output.write(buffer, 0, buffer.length);

int writtenBytes = 0;
int readBytes;
final byte[] buff = new byte[1024 * 12]; // 12 KB

while (mIsRunning && (readBytes = inputStream.read(buff)) != -1) {
    output.write(buff, 0, readBytes);
    writtenBytes += readBytes;
}

output.flush();
output.close();

Заголовки HTTP, которые записываются в MediaPlayer перед аудио.

private String buildHttpHeader(final int contentLength) {
    final StringBuilder sb = new StringBuilder();

    sb.append("HTTP/1.1 200 OK\r\n");
    sb.append("Content-Length: ").append(contentLength).append("\r\n");
    sb.append("Accept-Ranges: bytes\r\n" );
    sb.append("Content-Type: audio/mpeg\r\n");
    sb.append("Connection: close\r\n" );
    sb.append("\r\n");

    return sb.toString();
}

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

Опять же, это работает довольно хорошо Android 2.1 - 2.3, но в ICS MediaPlayer буферизует огромное количество этих данных перед игрой.

EDIT 2:

Дальнейшее тестирование показывает, что это также проблема SGS2 после обновления до Android 4.0.3. Таким образом, похоже, что буферизация MediaPlayer значительно изменилась в 4.0. Это расстраивает, поскольку API не дает возможности изменить поведение.

ИЗМЕНИТЬ 3:

Создана ошибка Android. Также добавьте комментарии и звездочку http://code.google.com/p/android/issues/detail?id=29870

EDIT 4:

Мой код воспроизведения довольно стандартный. У меня есть вызов start () на MediaPlayer в моем методе onPrepared ().

mCurrentPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mCurrentPlayer.setDataSource(url);
mCurrentPlayer.prepareAsync();

Попробовали это, используя только prepare (), а также рекомендованный способ ajacian81, но безрезультатно.

Я должен добавить, что недавно сотрудник Google вернулся ко мне по поводу моего вопроса и подтвердил, что размер буфера был намеренно увеличен в ICS (для контента HD). Разработчикам API было предложено добавить возможность устанавливать размер буфера на MediaPlayer.

Хотя я думаю, что этот запрос на изменение API был вокруг, прежде чем я пришел, поэтому я бы не советовал никому задерживать дыхание.


Можно ли увидеть код, с которого вы начинаете () в MediaPlayer?

Используете ли вы STREAM_MUSIC аудиопотока STREAM_MUSIC ?

player.setAudioStreamType(AudioManager.STREAM_MUSIC);

Вы также экспериментировали между player.prepareAsync (); и player.prepare () ;?

В прошлом году была аналогичная проблема, о которой я помню, где было принято решение: начать, приостановить, а затем перейти к началу ():

player.setAudioStreamType(AudioManager.STREAM_MUSIC); 
player.setDataSource(src); 
player.prepare(); 
player.start(); 
player.pause(); 
player.setOnPreparedListener(new OnPreparedListener() {     
@Override
                public void onPrepared(MediaPlayer mp) {
                    player.start();                
                }
          });

В этом случае вряд ли удастся исправить, но пока вы вращаете свои колеса, это может стоить выстрела.


Ответ на исходный вопрос напрямую. savedInstancestate имеет значение null, потому что ваша активность никогда не воссоздается.

Ваша деятельность будет воссоздана только с помощью пакета состояний, когда:

  • Изменения конфигурации, такие как изменение ориентации или языка телефона, для которого может потребоваться создание нового экземпляра активности.
  • Вы вернетесь в приложение из фона после того, как ОС уничтожила действие.

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

При тестировании вашего приветственного примера мира есть несколько способов уйти и вернуться к Activity.

  • Когда вы нажмете кнопку «Назад», действие завершено. Повторное запуск приложения - это новый экземпляр. Вы не возобновляете с фона вообще.
  • Когда вы нажимаете кнопку «домой» или используете переключатель задач, «Активность» переходит в фоновый режим. При переходе назад к приложению onCreate будет вызываться только в том случае, если действие должно быть уничтожено.

В большинстве случаев, если вы просто нажимаете кнопку «домой», а затем снова запускаете приложение, активность не нужно будет воссоздавать. Он уже существует в памяти, поэтому onCreate () не будет вызываться.

В разделе Настройки -> Параметры разработчика есть опция «Не выполнять действия». Когда это будет включено, Android всегда будет уничтожать действия и воссоздавать их, когда они будут созданы. Это отличный вариант оставить включенным при разработке, поскольку он имитирует худший сценарий. (Устройство с низкой памятью постоянно перерабатывает ваши действия).

Другие ответы ценны тем, что они учат вас правильным способам хранения состояния, но я не чувствовал, что они действительно ответили. ПОЧЕМУ ваш код работал не так, как вы ожидали.





android audio streaming music-player