ExoPlayer2 - How can I make a HTTP 301 redirect wo

2019-02-12 07:20发布

问题:

I started using ExoPlayer to stream some audio. All was well until I came across an URL that has a "301 Moved Permanently" redirect. ExoPlayer2 does not handle that by default.

I've already seen this thread: https://github.com/google/ExoPlayer/issues/423

There they say to add the new "allowCrossDomainRedirects" flag to either a HttpDataSource or UriDataSource. The problem is that I don't use either of those classes:

//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);

See how the ExtractorMediaSource requires a dataSourceFactory instead of a DataSource. In fact I can't even find the classes HttpDataSource and UriDataSource on ExoPlayer2. Looks like they have been removed.

Therefore I can't find a way to add the flag mentioned on the post. Can somebody help me?

回答1:

The problem described in the issue is about cross-protocol redirects (from http to https or vice versa). Exoplayer supports this, but you have to set allowCrossProtocolRedirects to true. Regular redirects (including 301 redirects) are supported by default. The redirect you're receiving is most likely a cross-protocol redirect.

To create the data source you're calling:

DefaultDataSourceFactory(Context context, String userAgent)

This constructor creates a DefaultHttpDataSourceFactory which has allowCrossProtocolRedirects set to false.

To change this, you need to call:

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

And use your own DefaultHttpDataSourceFactory with allowCrossProtocolRedirects set to true as the baseDataSourceFactory.

For example:

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
);

If you need to do this more often you can also create a helper method:

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;
}

This will allow cross-protocol redirects.

Sidenote: "301 Moved Permanently" means clients need to update their URL to the new one. "302 Found" is used for regular redirects. If possible, update the URLs that return "301 Moved Permanently".