Playing videos from storage is a lot more simple than streaming video from the server. There are many tasks that need to handled while streaming video like adaptive playback, composition, caching, bandwidth control, etc. Streaming video with android low-level API like MediaPlayer is complex. Android Streaming Video With  ExoPlayer 2 provides a big set of customization. Worlds largest video sharing network YouTube, Facebook, PlayMovies also uses ExoPlayer. Furthermore, there are more than 140,000 applications making use of ExoPlayer. In this tutorial, we will develop a simple video streaming application with ExoPlayer.

Download Source Code and Application

Demo Video

Android Streaming Video With ExoPlayer 2

Adding ExoPlayer Libray to Android Studio Project

Create a new android studio project or open existing project. Open Gradle Scripts -> build.gradle(Module App). Add ExoPlayer and IMA Extension dependency to your file as shown below.(Note: IAM Extension dependency is optional add it only if you want to show video ads in between your videos like YouTube)

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support:support-v4:26.1.0'
    /*Add ExoPlayer Dependency Here*/
    implementation 'com.google.android.exoplayer:exoplayer:r2.5.1'
    /* Optional IMA Extension Dependency If you want to show Video Ads
    in between Your videos Like Youtube */
    implementation 'com.google.android.exoplayer:extension-ima:r2.5.1'
}

Creating Full-Screen Activity

While playing video users needs to get full advantage of the screen that’s why we need to create full-screen immersive activity. Create a new class Package Name -> VideoStreamingActivity.java add the following code to it.

public class VideoStreamingActivity extends AppCompatActivity {
    private static final int UI_ANIMATION_DELAY = 300;
    private final Handler mHideHandler = new Handler();
    private View mContentView;
    private final Runnable mHidePart2Runnable = new Runnable() {
        @SuppressLint("InlinedApi")
        @Override
        public void run() {
            mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
        }
    };
    private final Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            hide();
        }
    };
 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_streaming);
        mContentView = findViewById(R.id.fullscreen_content);
     }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        delayedHide(100);
    }


    private void hide() {
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.hide();
        }
        mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
    }


    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }

}

Create new layout res->layout->activity_video_streaming.xml. This will be the layout for VideoStreamingActivity. Add the following lines to it

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black">

    <! – The primary full-screen view. This can be replaced with whatever view
         is needed to present your content, e.g. VideoView, SurfaceView,
         TextureView, etc. – >
    <FrameLayout
        android:id="@+id/fullscreen_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

</FrameLayout>

Adding SimpleExoPlayerView To Layout

SimpleExoPlayerView is a component that provides predefined video player skin. This component contains the surface view, player controller, etc. open res -> layout -> activity_video_streaming.xml and paste following lines inside fullscreen_content  FrameLayout as shown below.

<FrameLayout
        android:id="@+id/fullscreen_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!--Add SimpleExoPlayerView Here – >
        <com.google.android.exoplayer2.ui.SimpleExoPlayerView
            android:id="@+id/exoPlayerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:resize_mode="fill" />
    </FrameLayout>

Creating Media Source 

ExoPlayer does not take directly Video Url as input it takes media source as its input. There are many types of media sources like ExtractorMediaSourceConcatenatingMediaSource(Used for playing playlist), HlsMediaSource(Used for Live Streaming), DashMediaSource, etc. For our application, we will create ExtractorMediaSource. Open Package Name -> VideoStreamingActivity.java . Add the following function to it.

private MediaSource createMediaSource(String videoUrl) {
        //Getting UserAgent
        String UserAgent = Util.getUserAgent(this, getString(R.string.app_name));
        
        //Creating Media Source
        MediaSource contentMediaSource = new ExtractorMediaSource(Uri.parse(videoUrl),
                new DefaultHttpDataSourceFactory(UserAgent),
                new DefaultExtractorsFactory(),
                null, null);
        //return media source
        return contentMediaSource;
    }

Creating Media Source with Ads 

If you are creating quality video content. You want to earn something from it. Then ExoPlayer provides IMA extension. This extension provides video ads integration during video playback. If you want to create media source with ads then Open Package Name -> VideoStreamingActivity.java. Add the following function to it.

private ImaAdsMediaSource createMediaSourceWithAds(String videoUrl, SimpleExoPlayerView exoPlayerView) {
        //Getting UserAgent
        String UserAgent = Util.getUserAgent(this, getString(R.string.app_name));
        // Creating  Video Content Media Source
        MediaSource contentMediaSource = new ExtractorMediaSource(Uri.parse(videoUrl),
                new DefaultHttpDataSourceFactory(UserAgent),
                new DefaultExtractorsFactory(), null, null);
        //Creating  Ima Ads Loader 
        ImaAdsLoader imaAdsLoader = new ImaAdsLoader(this, Uri.parse(getResources().getString(R.string.ad_tag_url)));
        
        //Creating Video Content Media Source With Ads
        ImaAdsMediaSource contentMediaSourceWithAds = new ImaAdsMediaSource(
                contentMediaSource,//Video Content Media Source
                new DefaultDataSourceFactory(this, UserAgent),
                imaAdsLoader, 
                exoPlayerView.getOverlayFrameLayout());//Overlay During Ads Playback
        //return media source with ads
        return contentMediaSourceWithAds;
    }

Creating Video Player Configuration

Create new class for defining Video Player Configuration Package Name -> VideoPlayerConfig.java

public class VideoPlayerConfig {
    //Minimum Video you want to buffer while Playing
    public static final int MIN_BUFFER_DURATION = 25000;
    //Max Video you want to buffer during PlayBack
    public static final int MAX_BUFFER_DURATION = 30000;
    //Min Video you want to buffer before start Playing it
    public static final int MIN_PLAYBACK_START_BUFFER = 10000;
    //Min video You want to buffer when user resumes video
    public static final int MIN_PLAYBACK_RESUME_BUFFER = 10000;
    //Video Url
    public static final String VIDEO_URL = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_30mb.mp4";
}
  1. MIN_BUFFER_DURATION: Minimum Video you want to buffer while Playing
  2. MAX_BUFFER_DURATION: Max Video you want to buffer during PlayBack
  3. MIN_PLAYBACK_START_BUFFER: Min Video you want to buffer before start Playing it
  4. MIN_PLAYBACK_RESUME_BUFFER: Min video You want to buffer when user resumes video

Initializing ExoPlayer 

Now our Media Source and Video Player Configuration are ready. Define To initialize ExoPlayer create a new function initializePlayer() in Package Name -> VideoStreamingActivity.java. Add the following lines to it.

//Define Field for SimpleExoPlayer
    SimpleExoPlayer player;

    private void initializePlayer() {
        //Biding xml view to exoPlayerView object
        SimpleExoPlayerView exoPlayerView = findViewById(R.id.exoPlayerView);
        //Creating Load Control
        LoadControl loadControl = new DefaultLoadControl(
                new DefaultAllocator(true, 16),
                VideoPlayerConfig.MIN_BUFFER_DURATION,
                VideoPlayerConfig.MAX_BUFFER_DURATION,
                VideoPlayerConfig.MIN_PLAYBACK_START_BUFFER,
                VideoPlayerConfig.MIN_PLAYBACK_RESUME_BUFFER);

        //Initializing ExoPlayer
        player = ExoPlayerFactory.newSimpleInstance(
                new DefaultRenderersFactory(this),
                new DefaultTrackSelector(),
                loadControl);
        //binding exoPlayerView to SimpleExoPlayer
        exoPlayerView.setPlayer(player);
        //preparing player with media Source
        player.prepare(createMediaSource(VideoPlayerConfig.VIDEO_URL));
        //Uncomment following line remove above line if you want to play Ads between Video
        //player.prepare(createMediaSourceWithAds(VideoPlayerConfig.VIDEO_URL,exoPlayerView));
        //adding Listener to SimpleExoPlayer
        player.addListener(new Player.EventListener() {
            @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) {
                switch (playbackState) {
                    case Player.STATE_BUFFERING:
                        //Player is in state State buffering show some loading progress
                        //showProgress();
                        break;
                    case Player.STATE_READY:
                        //Player is ready to Play. Remove loading progress
                        // hideProgress();
                        break;
                }
            }

            @Override
            public void onRepeatModeChanged(int repeatMode) {
            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
            }

            @Override
            public void onPositionDiscontinuity() {
            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
            }
        });

    }

Managing Player with Activity Life Cycle

Now it is important to change player state during different activity lifecycle events like onPause(), onResume() and onDestroy() methods. Open Package Name -> VideoStreamingActivity.java add following lines to it.

/*   Activity Life Cycle*/
    @Override
    protected void onResume() {
        player.setPlayWhenReady(true);
        super.onResume();
    }

    @Override
    protected void onPause() {
        player.setPlayWhenReady(false);
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        player.release();
        super.onDestroy();
    }

Finally

Open Package Name -> VideoStreamingActivity.java initialize player inside onCreate() Method

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_streaming);
        mContentView = findViewById(R.id.fullscreen_content);
        mProgressBar = findViewById(R.id.progressBar);
        //initialize Player
        initializePlayer();
   }

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.loopwiki.androidvideostrammingsample">

   <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:screenOrientation="landscape"
            android:name=".VideoStreamingActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/title_activity_video_streaming"
            android:theme="@style/FullscreenTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
    <color name="black_overlay">#90000000</color>
    <color name="black">#000000</color>
</resources>

attrs.xml

right click res -> values folder and select New ->  Values resource file. Enter the name as attrs and press ok. Paste following lines in it.

<resources>

    <! – Declare custom theme attributes that allow changing which styles are
         used for button bars depending on the API level.
         ?android:attr/buttonBarStyle is new as of API 11 so this is
         necessary to support previous API levels. – >
    <declare-styleable name="ButtonBarContainerTheme">
        <attr name="metaButtonBarStyle" format="reference" />
        <attr name="metaButtonBarButtonStyle" format="reference" />
    </declare-styleable>

</resources>

strings.xml

add following strings to your res -> values -> strings.xml file.

<resources>
    <string name="app_name">AndroidVideoStrammingSample</string>
    <string name="ad_tag_url">https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&amp;iu=/124319096/external/ad_rule_samples&amp;ciu_szs=300x250&amp;ad_rule=1&amp;impl=s&amp;gdfp_req=1&amp;env=vp&amp;output=vmap&amp;unviewed_position_start=1&amp;cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostoptimizedpodbumper&amp;cmsid=496&amp;vid=short_onecue&amp;correlator=</string>
    <string name="title_activity_video_streaming">VideoStreamingActivity</string>
</resources>

styles.xml

Add following styles to your res -> values -> styles.xml  file.

<resources>
    <! – Base application theme. – >
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <! – Customize your theme here. – >
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="FullscreenTheme" parent="AppTheme">
        <item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@null</item>
        <item name="metaButtonBarStyle">?android:attr/buttonBarStyle</item>
        <item name="metaButtonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
    </style>

    <style name="FullscreenActionBarStyle" parent="Widget.AppCompat.ActionBar">
        <item name="android:background">@color/black_overlay</item>
    </style>

</resources>

Running  Application 

Run the application and see the results.

Android Streaming Video With ExoPlayer 2 - Output Ads
Android Streaming Video With ExoPlayer 2 - Video

If you still have any queries, please post them in the comments section below, I will be happy to help you.

Author

Hello there, My name is Amardeep founder of loopwiki.com. I have experience in many technologies like Android, Java, Php, etc. In this variety of technologies, I love Android App Development. If you have any idea and you want me to develop for you then let's have chat Conatct

45 Comments

  1. when ever we are watching match at that time some ads come out on screen in side and bottom then automatically screen should be minimised . so… i want to play that type of ads in exoplayer , what i have to do for that could u please help me……

  2. Is it possible to play custom ads ? Ads which are basically from a url ??

  3. Suggest me how do i insert custom video ads (url like mp4 of 10 to 15 sec) in AdsLoader instead of IMA ads?

  4. hi
    is there any way to play IMA midroll and postroll ads with VAST.If possible then how?

  5. karan singh Reply

    how can i play video from url that i can change. Like setup firebase to load url in exoplayer.

  6. Hello sir,
    How can I play DASH URL with Widevine DRM protection? As from research, I was able to play only DASH URL using DashMediaSource but then I am not being able to URL which are Widevine DRM protected.

    Can you please help?

    • I don’t think so there is any other way to play DRM protected videos. You should do some research probably you will get something

  7. Kartikpathe Reply

    but How can I get My Ad code i.e.Google Ads Publisher Id for showing ads and earn some revenue

    • You should visit google DPF website their you can get to what things needs to be done in order to place video ads

  8. Mayank Langalia Reply

    Hello sir. I need small help. I want to add my custom advertisement is it possible or not ? Also i want to add advertisement indication (Yellow dot). Please help me Im stuck last few days.

  9. Hi,
    Can you help me to How I can change embedded subtitle and track in Hls?

  10. Hi Amardeep, Can you please tell me how I can listen to ads events such as adError(), adPaused(), adResumed() and adFinished()?
    I have been trying to do this for the past 2 days, still no result.
    I have this code which is playing the ads but I can not listen to ads events:
    MediaSource mediaSourceWithAds = new AdsMediaSource(
    contentMediaSource,
    adMediaFactory,
    imaAdsLoader,
    playerView.getOverlayFrameLayout(),
    null,
    null);

    • You can create adsmanager with that you can listen to events like adError(), adPaused(), adResumed() and adFinished()

  11. Vivek Shukla Reply

    Hii Sir I followed the process but the video didn’t streamed

      • Ìn VideoPlayerConfig.class change he URL from VIDEO_URL to public static final String VIDEO_URL = “http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4”; it’s worksing with this url.

  12. Hi
    using the IMA Extension can we show ads in between the videos?

    • with SimpleExoPlayerView you cant’t set aspect ratio, instead you have to use surface view and there you can set aspect ratio

    • Yes for sure create hlsmedisource for m3u8 files it has several parameters as shown below
      HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, null);

  13. Android Developer Reply

    Can we play Facebook or Vimeo video in this player? If yes, how can I do that?

    • Thanks for your question, Facebook and Vimeo don’t provide there media source URLs as per my knowledge. But maybe there is a way to get these Media Source URLs by using there API. Read there API and find a way to obtain Media Source URLs. If you find Media Source URL then it is easy to implement with ExoPlayer.

      // Creating  Video Content Media Source
              MediaSource contentMediaSource = new ExtractorMediaSource(Uri.parse(MEDIA_SOURCE_URL),
                      new DefaultHttpDataSourceFactory(UserAgent),
                      new DefaultExtractorsFactory(), null, null);

      Now Media Source is ready, pass it to play with ExoPlayer
      player.prepare(contentMediaSource);
      To start Playing Video
      player.setPlayWhenReady(true);

  14. Kalpesh Bhangare Reply

    Good Work, Sir How can I create a playlist of video or audio using ExoPlayer?

    • Thank You Mate, You can use ConcatenatingMediaSource. Refer this example to create PlayList of video or audio using ExoPlayer

       File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
          File file1 = new File(file,"file1.mp4");
          File file2 = new File(file,"file2.mp4");
          File file3 = new File(file,"file3.mp4");
          MediaSource firstSource = new ExtractorMediaSource(Uri.parse(file1.getAbsolutePath()),mediaDataSourceFactory,new DefaultExtractorsFactory(),
                  mainHandler,eventLogger);
          MediaSource secondSource = new ExtractorMediaSource(Uri.parse(file2.getAbsolutePath()),mediaDataSourceFactory,new DefaultExtractorsFactory(),
                  mainHandler,eventLogger);
          MediaSource thirdSource = new ExtractorMediaSource(Uri.parse(file3.getAbsolutePath()),mediaDataSourceFactory,new DefaultExtractorsFactory(),
                  mainHandler,eventLogger);
          ConcatenatingMediaSource PlayListMediaSource= new ConcatenatingMediaSource(firstSource,secondSource,thirdSource);
      
        • I’m new to programming, could you show me how you put this list into this program? thank you

Write A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.