title: How to play multiple audio uri sequentially using exoplayer?
body: <p>I am trying to play audio using exoplayer. </p>
  
  <p>I have multiple files in a local directory and I want to play them sequentially. I am trying to add multiple to URIs to MediaSource, but I couldn't find the solution.</p>
  
  <p>Here, the first file is playing correctly but none of the rest. I am using the ExoPlayer version 2.9.2</p>
  
  <p>Note: In my case the files in the "Articles" folder will be updated dynamically while player is running.</p>
  
  <p>Please suggest a solution. My code:</p>
  
  <pre><code>class AudioPlayerService : Service() {
  
  private var player: SimpleExoPlayer? = null
  private var playerNotificationManager: PlayerNotificationManager? = null
  private var mediaSession: MediaSessionCompat? = null
  private var mediaSessionConnector: MediaSessionConnector? = null
  private var dataSourceFactory: DataSource.Factory? = null
  private var extractorsFactory: ExtractorsFactory? = null
  private var dynamicConcatenatingMediaSource: ConcatenatingMediaSource? = null
  
  override fun onCreate() {
      super.onCreate()
      val context: Context = this
      player = ExoPlayerFactory.newSimpleInstance(this)
      dataSourceFactory = DefaultDataSourceFactory(context, BuildConfig.APPLICATION_ID)
      extractorsFactory = DefaultExtractorsFactory()
  
      var file: File = File(Environment.getExternalStorageDirectory().absolutePath + "/Articles")
  
      /*for (i in file.listFiles()){
          Log.e("","" +file.listFiles())
      }*/
  
      var uri =
          Uri.parse(Environment.getExternalStorageDirectory().absolutePath + "/Articles" + "/article_tts" + 0 + ".wav")
  
  
      //if (dynamicConcatenatingMediaSource == null)
      dynamicConcatenatingMediaSource = ConcatenatingMediaSource()
      val mediaSource: MediaSource =
          ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(uri)
      dynamicConcatenatingMediaSource?.addMediaSource(mediaSource)
  
      player?.prepare(dynamicConcatenatingMediaSource)
      player?.setPlayWhenReady(true)
  
      player?.addListener(object : Player.EventListener {
          override fun onTracksChanged(
              trackGroups: TrackGroupArray?,
              trackSelections: TrackSelectionArray?
          ) {
  
          }
  
          override fun onPlayerError(error: ExoPlaybackException?) {
              stopSelf()
          }
  
          override fun onLoadingChanged(isLoading: Boolean) {
  
          }
  
          override fun onPositionDiscontinuity(reason: Int) {
  
          }
  
          override fun onRepeatModeChanged(repeatMode: Int) {
  
          }
  
          override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
  
          }
  
          override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {
  
          }
  
          override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
              if (playbackState == Player.STATE_ENDED) {
                  player?.stop()
                  stopSelf()
              }
          }
  
          override fun onSeekProcessed() {
  
          }
  
          override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {
  
          }
      })
  
      playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
          context,
          "playback_channel",
          R.string.playback_channel_name,
          7001,
          object : MediaDescriptionAdapter {
              override fun getCurrentContentTitle(player: Player): String {
                  return "Playlist"
              }
  
              override fun createCurrentContentIntent(player: Player): PendingIntent? {
                  return null
              }
  
              override fun getCurrentContentText(player: Player): String? {
                  return "Playlist Demo"
              }
  
              override fun getCurrentLargeIcon(
                  player: Player,
                  callback: BitmapCallback
              ): Bitmap? {
                  return getBitmap(context, R.drawable.ic_vikatan_logo_new)
              }
          }
      )
      playerNotificationManager?.setNotificationListener(object :
          PlayerNotificationManager.NotificationListener {
          override fun onNotificationStarted(
              notificationId: Int,
              notification: Notification
          ) {
              startForeground(notificationId, notification)
          }
  
          override fun onNotificationCancelled(notificationId: Int) {
              stopSelf()
          }
      })
  
      playerNotificationManager?.setPriority(NotificationCompat.PRIORITY_HIGH);
      playerNotificationManager?.setUseNavigationActions(false)
      playerNotificationManager?.setFastForwardIncrementMs(0)
      playerNotificationManager?.setRewindIncrementMs(0)
      playerNotificationManager?.setUsePlayPauseActions(true);
      playerNotificationManager?.setPlayer(player)
  
      mediaSession = MediaSessionCompat(context, "audio")
      mediaSession?.setActive(true)
      playerNotificationManager?.setMediaSessionToken(mediaSession?.getSessionToken())
  
      mediaSessionConnector = MediaSessionConnector(mediaSession)
      mediaSessionConnector?.setQueueNavigator(object : TimelineQueueNavigator(mediaSession) {
          override fun getMediaDescription(
              player: Player,
              windowIndex: Int
          ): MediaDescriptionCompat {
              return getMediaDescription(context)
          }
      })
      mediaSessionConnector?.setPlayer(player, null)
  }
  
  override fun onDestroy() {
      mediaSession!!.release()
      mediaSessionConnector!!.setPlayer(null, null)
      playerNotificationManager!!.setPlayer(null)
      player!!.release()
      player = null
      super.onDestroy()
  }
  
  override fun onBind(intent: Intent?): IBinder? {
      return null
  }
  
  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
      return START_STICKY
  }
  
  fun getBitmap(context: Context, @DrawableRes bitmapResource: Int): Bitmap {
      return (context.resources.getDrawable(bitmapResource) as BitmapDrawable).bitmap
  }
  
  fun getMediaDescription(context: Context?): MediaDescriptionCompat {
      val extras = Bundle()
      val bitmap: Bitmap = getBitmap(context!!, R.drawable.ic_vikatan_logo_new)
      extras.putParcelable(
          MediaMetadataCompat.METADATA_KEY_ALBUM_ART,
          bitmap
      )
      extras.putParcelable(
          MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON,
          bitmap
      )
      return MediaDescriptionCompat.Builder()
          .setMediaId("audio_id")
          .setIconBitmap(bitmap)
          .setTitle("Playlist")
          .setDescription("Playlist Demo")
          .setExtras(extras)
          .build()
  }
  }
  </code></pre>