Playing audio stream using ExoPlayer 2

Exoplayer is an Android application level media player developed by google for playing audio, video both locally and over the internet. Unlike the MediaPlayer API it is highly customizable. Minimum supported version for Exoplayer is Android 4.1 (API level 16). In this we are going to see a simple example of playing an audio stream URL using ‘Exoplayer 2’.

At first step we need to add the library in dependency section of the the build.gradle file by adding the following line

dependencies {
...
compile 'com.google.android.exoplayer:exoplayer:r2.4.2'
}

In this tutorial we are going to use a SimpleExoPlayer instance that requires three objects RendersFactory, TracSelector and LoadControl. Let’s create the objects one by one with appropriate parameters.

RendersFactory interface is used to build Renderer instances for use by a SimpleExoPlayer. Renderers are used to render individual components of the media. Let’s implement the RendersFactory by using the DefaultRendersFactory like below

renderersFactory = new DefaultRenderersFactory(getApplicationContext());

TrackSelector is used to select tracks provided by the MediaSource to be consumed by each of the available Renderers. We shall have look at how to build MediaSource object later on. Let’s create the TrackSelector by adding the following lines

bandwidthMeter = new DefaultBandwidthMeter(); //Provides estimates of the currently available bandwidth.
trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(trackSelectionFactory);

LoadControl is used to control when the MediaSource buffers more media, and how much media is buffered. In this example, we are going to use the default buffer settings.

loadControl = new DefaultLoadControl();

At this point we are ready to create the SimpleExoPlayer instance. We could also implement the ExoPlayer.EventListener in our Activity class and add this listener to our SimpleExoPlayer instance.

player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
player.addListener(this);

Now its time to create MediaSource. MediaSource defines the media to be played, loads the media, and from which the loaded media can be read. Let’s create the MediaSource in the following way

dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(), "ExoplayerDemo");
extractorsFactory = new DefaultExtractorsFactory();
mainHandler = new Handler();
mediaSource = new ExtractorMediaSource(Uri.parse(streamUrl),
                dataSourceFactory,
                extractorsFactory,
                mainHandler,
                null);

In the above we used DefaultDataSource instance that delegates to DefaultHttpDataSources for non-file/asset/content URIs and DefaultExtractorsFactory that provides an array of extractors for the formats MP4, fMP4, Matroska and WebM, Ogg Vorbis/FLAC, MP3, AAC, MPEG TS, MPEG PS, FLV, WAV, AC3, FLAC.
We have defined our streamUrl at the top like the following

private final String streamUrl = "http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws"; //bbc world service url

Finally we need to prepare the player with the MediaSource in the following way.

player.prepare(mediaSource);

To keep the example simple no user interface was created to play or pause the media stream. We are going to play the stream when the activity resumes by including the following line inside the Activity lifecycle method onResume()

player.setPlayWhenReady(true);

and going to pause the stream when the Activity is on pause state by adding the following line inside Activity life cycle method onPause()

player.setPlayWhenReady(true);

Our MainActivity class now looks like the following.

public class MainActivity extends AppCompatActivity implements ExoPlayer.EventListener {
 
 
    private Handler mainHandler;
    private RenderersFactory renderersFactory;
    private BandwidthMeter bandwidthMeter;
    private LoadControl loadControl;
    private DataSource.Factory dataSourceFactory;
    private ExtractorsFactory extractorsFactory;
    private MediaSource mediaSource;
    private TrackSelection.Factory trackSelectionFactory;
    private SimpleExoPlayer player;
    private final String streamUrl = "http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws"; //bbc world service url
    private TrackSelector trackSelector;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        renderersFactory = new DefaultRenderersFactory(getApplicationContext());
        bandwidthMeter = new DefaultBandwidthMeter();
        trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        trackSelector = new DefaultTrackSelector(trackSelectionFactory);
        loadControl = new DefaultLoadControl();
 
        player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
        player.addListener(this);
 
        dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(), "ExoplayerDemo");
        extractorsFactory = new DefaultExtractorsFactory();
        mainHandler = new Handler();
        mediaSource = new ExtractorMediaSource(Uri.parse(streamUrl),
                dataSourceFactory,
                extractorsFactory,
                mainHandler,
                null);
 
        player.prepare(mediaSource);
 
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        player.setPlayWhenReady(true);
        Toast.makeText(MainActivity.this, "Exoplayer is playing.", Toast.LENGTH_SHORT).show();
    }
 
    @Override
    protected void onPause() {
        super.onPause();
        player.setPlayWhenReady(false);
        Toast.makeText(MainActivity.this, "Exoplayer is on pause.", Toast.LENGTH_SHORT).show();
    }
 
    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest) {
 
    }
 
    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
 
    }
 
    @Override
    public void onLoadingChanged(boolean isLoading) {
 
    }
 
    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
 
    }
 
    @Override
    public void onPlayerError(ExoPlaybackException error) {
 
    }
 
    @Override
    public void onPositionDiscontinuity() {
 
    }
 
    @Override
    public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
 
    }
}

The resulting app looks like the following

The full source code can be downloaded from here

4 Comments

  1. Dima Basin

    finally a normal example. Thank you!

    Reply
  2. Gogun Letson

    I agree with Dima. First simple and normal example, easy to understand, after one day of searching the internet. Thank you !

    Reply
  3. Galados ext

    thanks for your tutorial, its work and simple to implement actually. really help me a lot how it works

    Reply
  4. ema86ct

    Thanks for sharing this, i’ve been spended a lot of time searching an understandable explanation like this, simple, direct and functional, thanks again bro!

    Reply

Leave a Comment

Your email address will not be published. Required fields are marked *