Manuela Manuela - 3 months ago 94
Android Question

Dynamic playlists with Exoplayer 2

I'd like to use ExoPlayer2 with playlists having possibility to dinamically change the tracks (add or remove them from playlist) and change the loop settings.

Since ConcatenatingMediaSource has static arrays (and not lists), I'm implementing a DynamicMediaSource, like Concatenating one but with lists instead of arrays and one mode method addSource to add one more media source to the list.

public void addSource(MediaSource mediaSource) {
duplicateFlags = buildDuplicateFlags(this.mediaSources);
prepareSource(mediaSources.size() -1);

When I invoke addSource

MediaSource ms = buildMediaSource(mynewuri, null);

the track is added to the arrays but it seems something is missing because I always obtain ArrayOutOfBoundsException in createPeriod method.

In createPeriod the method


is trying to access the index = mediaSources.size().

Can you help me?


I eventually managed it. It was my fault during the conversion from arrays to lists. I had to use SparseArrays for timelines and manifests and everything began to work.

In the DynamicMediaSource simply set the following types:

private final List<MediaSource> mediaSources;
private final SparseArray<Timeline> timelines;
private final SparseArray<Object> manifests;
private final Map<MediaPeriod, Integer> sourceIndexByMediaPeriod;
private SparseArray<Boolean> duplicateFlags;

you have to use sparse arrays to set the proper values into the timelines and manifests in the method

private void handleSourceInfoRefreshed(int sourceFirstIndex, Timeline sourceTimeline,
                                       Object sourceManifest) {
    // Set the timeline and manifest.
    timelines.put(sourceFirstIndex, sourceTimeline);
    manifests.put(sourceFirstIndex, sourceManifest);

    // Also set the timeline and manifest for any duplicate entries of the same source.
    for (int i = sourceFirstIndex + 1; i < mediaSources.size(); i++) {
        if (mediaSources.get(i).equals(mediaSources.get(sourceFirstIndex))) {
            timelines.put(i, sourceTimeline);
            manifests.put(i, sourceManifest);

    for(int i= 0; i<mediaSources.size(); i++){
        if(timelines.get(i) == null){
            // Don't invoke the listener until all sources have timelines.

    timeline = new DynamicTimeline(new ArrayList(asList(timelines)));
    listener.onSourceInfoRefreshed(timeline, new ArrayList(asList(manifests)));