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)