title: Exoplayer player video mp4 e stream m3u8
body: <p>Is there a way to run an exoplayer with both mp4 and stream m3u8 videos?</p>
  
  <p>I tried but I could not find a solution.</p>
  
  <p>I found the following sources for testing.</p>
  
  <p>Video mp4: <a href="https://www.w3schools.com/html/mov_bbb.mp4" rel="nofollow noreferrer">here</a></p>
  
  <p>Stream m3u8: <a href="https://live3-mediaset-it.akamaized.net/content/hls_clr_xo/live/channel(ch09)/Stream(02)/index.m3u8" rel="nofollow noreferrer">here</a></p>
  
  <p>This is the code I wrote with the mp4 videos works, but with m3u8, no.</p>
  
  <p>I made several attempts, but I did not succeed, I was thinking of using HlsMediaSource but I could not make it work.</p>
  
  <p>Error, the following function is called within <code>SimpleVideoStream.java</code>:</p>
  
  <pre><code>public void onPlayerError(ExoPlaybackException error) {
  </code></pre>
  
  <p> 
  Code:</p>
  
  <p>AndroidManifest:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ui.exoplayer"&gt;
  
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
      &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
  
      &lt;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"&gt;
          &lt;activity android:name=".MainActivity"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
          &lt;activity
              android:name=".SimpleVideoStream"
              android:configChanges="orientation|screenSize"
              android:screenOrientation="landscape" /&gt;
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p>MainActivity: </p>
  
  <pre><code>import android.content.Intent;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  
  public class MainActivity extends AppCompatActivity {
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          final Intent intent = new Intent(this, SimpleVideoStream.class);
          Bundle extras = new Bundle();
          extras.putString("title", "Big Buck Bunny");
          //extras.putString("url", "https://www.w3schools.com/html/mov_bbb.mp4");
          extras.putString("url", "https://live3-mediaset-it.akamaized.net/content/hls_clr_xo/live/channel(ch09)/Stream(02)/index.m3u8");
          extras.putString("sub", "https://pastebin.com/raw/A0fDHxgK");
          extras.putBoolean("subShow", true);
          intent.putExtras(extras);
          startActivity(intent);
      }
  }
  </code></pre>
  
  <p>SimpleVideoStream:</p>
  
  <pre><code>package com.ui.exoplayer;
  
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.net.Uri;
  import android.os.Bundle;
  import android.support.annotation.Nullable;
  import android.support.v7.app.AlertDialog;
  import android.support.v7.app.AppCompatActivity;
  import android.view.View;
  import android.view.WindowManager;
  
  import com.google.android.exoplayer2.C;
  import com.google.android.exoplayer2.DefaultLoadControl;
  import com.google.android.exoplayer2.ExoPlaybackException;
  import com.google.android.exoplayer2.ExoPlayer;
  import com.google.android.exoplayer2.ExoPlayerFactory;
  import com.google.android.exoplayer2.Format;
  import com.google.android.exoplayer2.LoadControl;
  import com.google.android.exoplayer2.PlaybackParameters;
  import com.google.android.exoplayer2.SimpleExoPlayer;
  import com.google.android.exoplayer2.Timeline;
  import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
  import com.google.android.exoplayer2.extractor.ExtractorsFactory;
  import com.google.android.exoplayer2.source.ExtractorMediaSource;
  import com.google.android.exoplayer2.source.MediaSource;
  import com.google.android.exoplayer2.source.MergingMediaSource;
  import com.google.android.exoplayer2.source.SingleSampleMediaSource;
  import com.google.android.exoplayer2.source.TrackGroupArray;
  import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
  import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
  import com.google.android.exoplayer2.trackselection.TrackSelection;
  import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
  import com.google.android.exoplayer2.trackselection.TrackSelector;
  import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
  import com.google.android.exoplayer2.upstream.BandwidthMeter;
  import com.google.android.exoplayer2.upstream.DataSource;
  import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
  import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
  import com.google.android.exoplayer2.util.MimeTypes;
  import com.google.android.exoplayer2.util.Util;
  
  public class SimpleVideoStream extends AppCompatActivity implements ExoPlayer.EventListener {
      public static final int PERMISSIONS_REQUEST_CODE = 0;
  
      SimpleExoPlayerView playerView;
      SimpleExoPlayer player;
      DataSource.Factory dataSourceFactory;
      MediaSource videoSource;
  
      String url, sub;
      Boolean showTitle = true, showSub = false;
  
      @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          Bundle b = getIntent().getExtras();
          url = b.getString("url", "");
          sub = b.getString("sub", "");
  
          this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  
          playerView = (SimpleExoPlayerView) findViewById(R.id.exo_player_view);
  
          // 1. Create a default TrackSelector
          BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
          TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
          TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
  
          // 2. Create a default LoadControl
          LoadControl loadControl = new DefaultLoadControl();
  
          // 3. Create the player
          player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
          playerView.setPlayer(player);
          playerView.setKeepScreenOn(true);
          playerView.setRewindIncrementMs(5 * 1000);
          playerView.setFastForwardIncrementMs(5 * 1000);
  
          // Produces DataSource instances through which media data is loaded.
          dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));
  
          // Produces Extractor instances for parsing the media data.
          final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
  
          // This is the MediaSource representing the media to be played.
          videoSource = new ExtractorMediaSource(Uri.parse(url), dataSourceFactory, extractorsFactory, null, null);
  
          // Prepare the player with the source.
          player.addListener(this);
          player.prepare(videoSource);
          playerView.requestFocus();
          player.setPlayWhenReady(true);// to play video when ready. Use false to pause a video
  
          if (!sub.equals("") &amp;&amp; b.getBoolean("subShow")) addSub(sub);
      }
  
  
      @Override
      protected void onPause() {
          super.onPause();
          if (player != null) {
              player.setPlayWhenReady(false); //to pause a video because now our video player is not in focus
          }
      }
  
      @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 ExoPlayer.STATE_BUFFERING:
                  //You can use progress dialog to show user that video is preparing or buffering so please wait
                  break;
              case ExoPlayer.STATE_IDLE:
                  //idle state
                  break;
              case ExoPlayer.STATE_READY:
                  // dismiss your dialog here because our video is ready to play now
                  break;
              case ExoPlayer.STATE_ENDED:
                  // do your processing after ending of video
                  break;
          }
      }
  
      @Override
      public void onPlayerError(ExoPlaybackException error) {
          // show user that something went wrong. I am showing dialog but you can use your way
          AlertDialog.Builder adb = new AlertDialog.Builder(this);
          adb.setTitle("Could not able to stream video");
          adb.setMessage("It seems that something is going wrong.\nPlease try again.");
          adb.setPositiveButton("OK", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int which) {
                  dialog.dismiss();
                  finish(); // take out user from this activity. you can skip this
              }
          });
          AlertDialog ad = adb.create();
          ad.show();
      }
  
  
      @Override
      public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
      }
  
      @Override
      public void onRepeatModeChanged(int repeatMode) {
      }
  
      @Override
      public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
      }
  
      @Override
      public void onPositionDiscontinuity(int reason) {
      }
  
      @Override
      public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
      }
  
      @Override
      public void onSeekProcessed() {
      }
  
      @Override
      public void onWindowFocusChanged(boolean hasFocus) {
          super.onWindowFocusChanged(hasFocus);
          if (hasFocus) {
              getWindow().getDecorView().setSystemUiVisibility(
                      View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                              | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                              | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                              | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                              | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                              | View.SYSTEM_UI_FLAG_FULLSCREEN
                              | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
          }
      }
  
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          super.onActivityResult(requestCode, resultCode, data);
      }
  
      private void removeSub() {
          showSub = false;
          final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
          videoSource = new ExtractorMediaSource(Uri.parse(url), dataSourceFactory, extractorsFactory, null, null);
          player.prepare(videoSource, false, false);
      }
  
      private void addSub(String sub) {
          removeSub();
          showSub = true;
          Format textFormat = Format.createTextSampleFormat(null, MimeTypes.APPLICATION_SUBRIP, null, Format.NO_VALUE, Format.NO_VALUE, "en", null, Format.OFFSET_SAMPLE_RELATIVE);
          MediaSource textMediaSource = new SingleSampleMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(sub), textFormat, C.TIME_UNSET);
          videoSource = new MergingMediaSource(videoSource, textMediaSource);
          player.prepare(videoSource, false, false);
      }
  
  }
  </code></pre>