ExoPlayer2 - Как я могу заставить перенаправление HTTP 301 работать?

Я начал использовать ExoPlayer для потоковой передачи аудио. Все было хорошо, пока я не наткнулся на URL с перенаправлением "301 Moved Permanently". ExoPlayer2 не обрабатывает это по умолчанию.

Я уже видел эту тему: https://github.com/google/ExoPlayer/issues/423

Там говорят добавить новый флаг "allowCrossDomainRedirects" в HttpDataSource или UriDataSource. Проблема в том, что я не использую ни один из этих классов:

//I am NOT using SimpleExoPlayer because I need a different renderer.
exoPlayer = ExoPlayerFactory.newInstance(renderers, trackSelector, loadControl);

final DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
            context,
            Util.getUserAgent(context, applicationInfo.getAppName())
);

// Produces Extractor instances for parsing the media data.
final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

// This is the MediaSource representing the media to be played.
MediaSource mediaSource = new ExtractorMediaSource(
            Uri.parse(media.getUriString()) /* uri */,
            dataSourceFactory,
            extractorsFactory,
            10,
            null /* eventHandler */,
            null /* eventListener */);

exoPlayer.prepare(mediaSource);

Посмотрите, как ExtractorMediaSource требует dataSourceFactory вместо DataSource. На самом деле я даже не могу найти классы HttpDataSource и UriDataSource на ExoPlayer2. Похоже, они были удалены.

Поэтому я не могу найти способ добавить флаг, упомянутый в сообщении. Кто-нибудь может мне помочь?

5 ответов

Решение

Проблема, описанная в проблеме, связана с межпротокольными перенаправлениями (с http на https или наоборот). Exoplayer поддерживает это, но вы должны установить allowCrossProtocolRedirects в true, Регулярные перенаправления (включая перенаправления 301) поддерживаются по умолчанию. Перенаправление, которое вы получаете, скорее всего, является межпротокольным перенаправлением.

Чтобы создать источник данных, который вы вызываете:

DefaultDataSourceFactory(Context context, String userAgent)

Этот конструктор создает DefaultHttpDataSourceFactory у которого есть allowCrossProtocolRedirects установлен в false,

Чтобы изменить это, вам нужно позвонить:

DefaultDataSourceFactory(Context context, TransferListener<? super DataSource> listener,
  DataSource.Factory baseDataSourceFactory)

И использовать свой собственный DefaultHttpDataSourceFactory с allowCrossProtocolRedirects установлен в true как baseDataSourceFactory,

Например:

String userAgent = Util.getUserAgent(context, applicationInfo.getAppName());

// Default parameters, except allowCrossProtocolRedirects is true
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
    userAgent,
    null /* listener */,
    DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
    DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
    true /* allowCrossProtocolRedirects */
);

DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
    context,
    null /* listener */,
    httpDataSourceFactory
);

Если вам нужно делать это чаще, вы также можете создать вспомогательный метод:

public static DefaultDataSourceFactory createDataSourceFactory(Context context,
        String userAgent, TransferListener<? super DataSource> listener) {
    // Default parameters, except allowCrossProtocolRedirects is true
    DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
        userAgent,
        listener,
        DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
        DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
        true /* allowCrossProtocolRedirects */
    );

    DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
        context,
        listener,
        httpDataSourceFactory
    );

    return dataSourceFactory;
}

Это позволит кросс-протокол перенаправления.

Знак "301 перемещен навсегда" означает, что клиенты должны обновить свой URL-адрес на новый. "302 найдено" используется для регулярных перенаправлений. Если возможно, обновите URL-адреса, которые возвращают "301 перемещено навсегда".

попробуй это:

      // Build a HttpDataSource.Factory with cross-protocol redirects enabled.
HttpDataSource.Factory httpDataSourceFactory =
    new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true);

// Wrap the HttpDataSource.Factory in a DefaultDataSource.Factory, which adds in
// support for requesting data from other sources (e.g., files, resources, etc).
DefaultDataSource.Factory dataSourceFactory =
    new DefaultDataSource.Factory(context, httpDataSourceFactory);

// Inject the DefaultDataSourceFactory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory))
        .build();

Меня устраивает.

Принятый ответ выглядит немного устаревшим, потому что класс DefaultHttpDataSource устарел, и мы предполагаем заменить его на DefaultHttpDataSource.Factory, см. официальную документацию .

Итак, вместо

      DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
    userAgent,
    null /* listener */,
    DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
    DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
    true /* allowCrossProtocolRedirects */
);

мы могли бы

          final DefaultHttpDataSource.Factory defaultDataSourceFactory = new DefaultHttpDataSource
    .Factory()
    .setUserAgent(userAgent)
    .setTransferListener(listener)     
.setConnectTimeoutMs(DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS)
    .setReadTimeoutMs(DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS)
    .setAllowCrossProtocolRedirects(true);

Также не забудьте использовать, если вам нужно

      final DefaultHttpDataSource defaultDataSource = defaultDataSourceFactory.createDataSource();

И, наконец, угадайте, что: DefaultDataSourceFactory также устарела, и вместо этого мы должны использовать DefaultDataSource.Factory.

Не забудьте указать правильный android:usesCleartextTraffic="true" в разделе приложения манифеста. Мой код для инициализации ExoPlayer с поддержкой http выглядит так:

      String userAgent = Util.getUserAgent(this, "my app name for example");

HttpDataSource.Factory httpDataSourceFactory =
            new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true);

player = new ExoPlayer.Builder(this)
            .setMediaSourceFactory(
                    new DefaultMediaSourceFactory(this)
                            .setDataSourceFactory(httpDataSourceFactory))
            .build();

оно работает

      val httpDataSourceFactory = DefaultHttpDataSourceFactory(Util.getUserAgent(context, "Player"),null,DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
        DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
        true)

val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(context, null, httpDataSourceFactory)
    
Другие вопросы по тегам