public class

DefaultDownloaderFactory

extends java.lang.Object

implements DownloaderFactory

 java.lang.Object

↳androidx.media3.exoplayer.offline.DefaultDownloaderFactory

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-exoplayer', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-exoplayer
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-exoplayer:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

Default DownloaderFactory, supporting creation of progressive, DASH, HLS and SmoothStreaming downloaders. Note that for the latter three, the corresponding library module must be built into the application.

Summary

Constructors
publicDefaultDownloaderFactory(CacheDataSource.Factory cacheDataSourceFactory)

Creates an instance.

publicDefaultDownloaderFactory(CacheDataSource.Factory cacheDataSourceFactory, java.util.concurrent.Executor executor)

Creates an instance.

Methods
public DownloadercreateDownloader(DownloadRequest request)

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public DefaultDownloaderFactory(CacheDataSource.Factory cacheDataSourceFactory)

Deprecated: Use DefaultDownloaderFactory.DefaultDownloaderFactory(CacheDataSource.Factory, Executor).

Creates an instance.

Parameters:

cacheDataSourceFactory: A for the cache into which downloads will be written.

public DefaultDownloaderFactory(CacheDataSource.Factory cacheDataSourceFactory, java.util.concurrent.Executor executor)

Creates an instance.

Parameters:

cacheDataSourceFactory: A for the cache into which downloads will be written.
executor: An java.util.concurrent.Executor used to download data. Passing Runnable::run will cause each download task to download data on its own thread. Passing an java.util.concurrent.Executor that uses multiple threads will speed up download tasks that can be split into smaller parts for parallel execution.

Methods

public Downloader createDownloader(DownloadRequest request)

Source

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.media3.exoplayer.offline;

import android.util.SparseArray;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.datasource.cache.CacheDataSource;
import java.lang.reflect.Constructor;
import java.util.concurrent.Executor;

/**
 * Default {@link DownloaderFactory}, supporting creation of progressive, DASH, HLS and
 * SmoothStreaming downloaders. Note that for the latter three, the corresponding library module
 * must be built into the application.
 */
@UnstableApi
public class DefaultDownloaderFactory implements DownloaderFactory {

  private static final SparseArray<Constructor<? extends Downloader>> CONSTRUCTORS =
      createDownloaderConstructors();

  private final CacheDataSource.Factory cacheDataSourceFactory;
  private final Executor executor;

  /**
   * Creates an instance.
   *
   * @param cacheDataSourceFactory A {@link CacheDataSource.Factory} for the cache into which
   *     downloads will be written.
   * @deprecated Use {@link #DefaultDownloaderFactory(CacheDataSource.Factory, Executor)}.
   */
  @Deprecated
  public DefaultDownloaderFactory(CacheDataSource.Factory cacheDataSourceFactory) {
    this(cacheDataSourceFactory, /* executor= */ Runnable::run);
  }

  /**
   * Creates an instance.
   *
   * @param cacheDataSourceFactory A {@link CacheDataSource.Factory} for the cache into which
   *     downloads will be written.
   * @param executor An {@link Executor} used to download data. Passing {@code Runnable::run} will
   *     cause each download task to download data on its own thread. Passing an {@link Executor}
   *     that uses multiple threads will speed up download tasks that can be split into smaller
   *     parts for parallel execution.
   */
  public DefaultDownloaderFactory(
      CacheDataSource.Factory cacheDataSourceFactory, Executor executor) {
    this.cacheDataSourceFactory = Assertions.checkNotNull(cacheDataSourceFactory);
    this.executor = Assertions.checkNotNull(executor);
  }

  @Override
  public Downloader createDownloader(DownloadRequest request) {
    @C.ContentType
    int contentType = Util.inferContentTypeForUriAndMimeType(request.uri, request.mimeType);
    switch (contentType) {
      case C.TYPE_DASH:
      case C.TYPE_HLS:
      case C.TYPE_SS:
        return createDownloader(request, contentType);
      case C.TYPE_OTHER:
        return new ProgressiveDownloader(
            new MediaItem.Builder()
                .setUri(request.uri)
                .setCustomCacheKey(request.customCacheKey)
                .build(),
            cacheDataSourceFactory,
            executor);
      default:
        throw new IllegalArgumentException("Unsupported type: " + contentType);
    }
  }

  private Downloader createDownloader(DownloadRequest request, @C.ContentType int contentType) {
    @Nullable Constructor<? extends Downloader> constructor = CONSTRUCTORS.get(contentType);
    if (constructor == null) {
      throw new IllegalStateException("Module missing for content type " + contentType);
    }
    MediaItem mediaItem =
        new MediaItem.Builder()
            .setUri(request.uri)
            .setStreamKeys(request.streamKeys)
            .setCustomCacheKey(request.customCacheKey)
            .build();
    try {
      return constructor.newInstance(mediaItem, cacheDataSourceFactory, executor);
    } catch (Exception e) {
      throw new IllegalStateException(
          "Failed to instantiate downloader for content type " + contentType);
    }
  }

  private static SparseArray<Constructor<? extends Downloader>> createDownloaderConstructors() {
    SparseArray<Constructor<? extends Downloader>> array = new SparseArray<>();
    try {
      array.put(
          C.TYPE_DASH,
          getDownloaderConstructor(
              Class.forName("androidx.media3.exoplayer.dash.offline.DashDownloader")));
    } catch (ClassNotFoundException e) {
      // Expected if the app was built without the DASH module.
    }

    try {
      array.put(
          C.TYPE_HLS,
          getDownloaderConstructor(
              Class.forName("androidx.media3.exoplayer.hls.offline.HlsDownloader")));
    } catch (ClassNotFoundException e) {
      // Expected if the app was built without the HLS module.
    }
    try {
      array.put(
          C.TYPE_SS,
          getDownloaderConstructor(
              Class.forName("androidx.media3.exoplayer.smoothstreaming.offline.SsDownloader")));
    } catch (ClassNotFoundException e) {
      // Expected if the app was built without the SmoothStreaming module.
    }
    return array;
  }

  private static Constructor<? extends Downloader> getDownloaderConstructor(Class<?> clazz) {
    try {
      return clazz
          .asSubclass(Downloader.class)
          .getConstructor(MediaItem.class, CacheDataSource.Factory.class, Executor.class);
    } catch (NoSuchMethodException e) {
      // The downloader is present, but the expected constructor is missing.
      throw new IllegalStateException("Downloader constructor missing", e);
    }
  }
}