ExoPlayer は、オフライン再生用にメディアをダウンロードする機能を提供します。ほとんどの
ダウンロードは、アプリがインストールされていても
説明します。これらのユースケースでは、アプリで DownloadService
をサブクラス化し、
ダウンロードを追加、削除、制御するコマンドをサービスに送信します。「
次の図は、関連する主なクラスを示しています。
DownloadService
:DownloadManager
をラップしてコマンドを転送します。「 サービスにより、アプリが実行中の場合でもDownloadManager
の実行を継続できる できます。DownloadManager
: 複数のダウンロード、読み込み(および保存)を管理しますDownloadIndex
からの状態(および状態)、ダウンロードの開始と停止は ネットワーク接続などの要件に 専念できますダウンロード マネージャーは通常、ダウンロードしたデータをHttpDataSource
を実行して、Cache
に書き込みます。DownloadIndex
: ダウンロードの状態を保持します。
DownloadService の作成
DownloadService
を作成するには、サブクラス化して実装します。
抽象メソッドの例:
getDownloadManager()
: 使用するDownloadManager
を返します。getScheduler()
: オプションのScheduler
を返します。これにより、 サービスに送信されます。 ExoPlayer は次の実装を提供します。 <ph type="x-smartling-placeholder">- </ph>
PlatformScheduler
: JobScheduler を使用します(最小 API は 21)。詳しくは、 PlatformScheduler の javadocs でアプリの権限の要件を確認してください。WorkManagerScheduler
: WorkManager を使用します。
getForegroundNotification()
: アプリケーションの起動時に表示される通知を返します。 フォアグラウンドで実行されている場合です。次を使用:DownloadNotificationHelper.buildProgressNotification
- 作成 表示されます。
最後に、AndroidManifest.xml
ファイルでサービスを定義します。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<application>
<service android:name="com.myapp.MyDownloadService"
android:exported="false"
android:foregroundServiceType="dataSync">
<!-- This is needed for Scheduler -->
<intent-filter>
<action android:name="androidx.media3.exoplayer.downloadService.action.RESTART"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
ExoPlayer の DemoDownloadService
と AndroidManifest.xml
を参照
デモアプリをご覧ください
DownloadManager を作成する
次のコード スニペットは、DownloadManager
をインスタンス化する方法を示しています。
これは、DownloadService
の getDownloadManager()
で返すことができます。
Kotlin
// Note: This should be a singleton in your app. val databaseProvider = StandaloneDatabaseProvider(context) // A download cache should not evict media, so should use a NoopCacheEvictor. val downloadCache = SimpleCache(downloadDirectory, NoOpCacheEvictor(), databaseProvider) // Create a factory for reading the data from the network. val dataSourceFactory = DefaultHttpDataSource.Factory() // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up // download tasks that can be split into smaller parts for parallel execution. Applications that // already have an executor for background downloads may wish to reuse their existing executor. val downloadExecutor = Executor(Runnable::run) // Create the download manager. val downloadManager = DownloadManager(context, databaseProvider, downloadCache, dataSourceFactory, downloadExecutor) // Optionally, properties can be assigned to configure the download manager. downloadManager.requirements = requirements downloadManager.maxParallelDownloads = 3
Java
// Note: This should be a singleton in your app. databaseProvider = new StandaloneDatabaseProvider(context); // A download cache should not evict media, so should use a NoopCacheEvictor. downloadCache = new SimpleCache(downloadDirectory, new NoOpCacheEvictor(), databaseProvider); // Create a factory for reading the data from the network. dataSourceFactory = new DefaultHttpDataSource.Factory(); // Choose an executor for downloading data. Using Runnable::run will cause each download task to // download data on its own thread. Passing an executor that uses multiple threads will speed up // download tasks that can be split into smaller parts for parallel execution. Applications that // already have an executor for background downloads may wish to reuse their existing executor. Executor downloadExecutor = Runnable::run; // Create the download manager. downloadManager = new DownloadManager( context, databaseProvider, downloadCache, dataSourceFactory, downloadExecutor); // Optionally, setters can be called to configure the download manager. downloadManager.setRequirements(requirements); downloadManager.setMaxParallelDownloads(3);
具体的な例については、デモアプリの DemoUtil
をご覧ください。
ダウンロードの追加
ダウンロードを追加するには、DownloadRequest
を作成して
DownloadService
。アダプティブ ストリームの場合は、DownloadHelper
を使用して
DownloadRequest
をビルドします。次の
次の例は、ダウンロード リクエストを作成する方法を示しています。
Kotlin
val downloadRequest = DownloadRequest.Builder(contentId, contentUri).build()
Java
DownloadRequest downloadRequest = new DownloadRequest.Builder(contentId, contentUri).build();
この例では、contentId
はコンテンツの一意の識別子です。単純なケースでは
多くの場合、contentUri
は contentId
として使用できますが、アプリは無料で使用できます
ユースケースに最適な ID スキームを
選択できますDownloadRequest.Builder
には次も存在します
いくつかのオプションセッターがあります。たとえば、setKeySetId
と setData
は、次の目的で使用できます。
アプリがダウンロードと関連付ける DRM とカスタムデータを設定する
できます。コンテンツの MIME タイプは setMimeType
を使用して指定できます。
contentUri
からコンテンツ タイプを推測できない場合のヒントとして使用します。
作成したら、リクエストを DownloadService
に送信して、
ダウンロード:
Kotlin
DownloadService.sendAddDownload( context, MyDownloadService::class.java, downloadRequest, /* foreground= */ false )
Java
DownloadService.sendAddDownload( context, MyDownloadService.class, downloadRequest, /* foreground= */ false);
この例では、MyDownloadService
がアプリの DownloadService
サブクラスであり、
foreground
パラメータはサービスを
使用します。アプリがすでにフォアグラウンドにある場合、foreground
このパラメータは通常 false
に設定する必要があります。これは、DownloadService
によって
処理する必要があると判断した場合、自身をフォアグラウンドに表示します。
ダウンロードを削除しています
ダウンロードを削除するには、DownloadService
に delete コマンドを送信します。
ここで、contentId
には削除するダウンロードを指定します。
Kotlin
DownloadService.sendRemoveDownload( context, MyDownloadService::class.java, contentId, /* foreground= */ false )
Java
DownloadService.sendRemoveDownload( context, MyDownloadService.class, contentId, /* foreground= */ false);
次のキーでダウンロードしたデータをすべて削除することもできます。
DownloadService.sendRemoveAllDownloads
。
ダウンロードの開始と停止
ダウンロードは、次の 4 つの条件が満たされた場合にのみ進行します。
- ダウンロードに停止理由がない。
- ダウンロードは一時停止されません。
- ダウンロードを続行するための要件を満たしています。要件では、 許可するネットワーク タイプとデバイスを制限する制約を設定できます。 アイドル状態または充電器に接続している。
- 並列ダウンロードの最大数を超えていません。
これらすべての条件は、コマンドを
DownloadService
。
ダウンロードの停止理由の設定とクリア
1 つまたは複数のダウンロードを停止する理由を設定できます。
Kotlin
// Set the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService::class.java, contentId, stopReason, /* foreground= */ false ) // Clear the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService::class.java, contentId, Download.STOP_REASON_NONE, /* foreground= */ false )
Java
// Set the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService.class, contentId, stopReason, /* foreground= */ false); // Clear the stop reason for a single download. DownloadService.sendSetStopReason( context, MyDownloadService.class, contentId, Download.STOP_REASON_NONE, /* foreground= */ false);
stopReason
にはゼロ以外の任意の値を指定できます(Download.STOP_REASON_NONE = 0
は
ダウンロードが停止しないことを示す特別な値)。次があるアプリ:
複数の理由でダウンロードを停止する場合は、
その理由を確認できますすべての停止理由を設定およびクリアする
ダウンロードは、Google Play Console の
1 回のダウンロード。ただし、contentId
は null
に設定する必要があります。
ダウンロードの停止理由が 0 以外の場合、
Download.STATE_STOPPED
状態。停止理由は
DownloadIndex
。アプリケーション プロセスが強制終了されても保持されます。
確認しました。
すべてのダウンロードを一時停止、再開しています
すべてのダウンロードの一時停止と再開は次のように行えます。
Kotlin
// Pause all downloads. DownloadService.sendPauseDownloads( context, MyDownloadService::class.java, /* foreground= */ false ) // Resume all downloads. DownloadService.sendResumeDownloads( context, MyDownloadService::class.java, /* foreground= */ false )
Java
// Pause all downloads. DownloadService.sendPauseDownloads(context, MyDownloadService.class, /* foreground= */ false); // Resume all downloads. DownloadService.sendResumeDownloads(context, MyDownloadService.class, /* foreground= */ false);
一時停止されたダウンロードは Download.STATE_QUEUED
状態になります。
停止理由を設定するとは異なり、このアプローチでは状態は保持されません。
できます。これは、DownloadManager
のランタイム状態にのみ影響します。
ダウンロードを進行させるための要件を設定する
Requirements
を使用すると、満たす必要がある制約を指定できます。
ダウンロードを続行します。要件を設定するには
DownloadManager
を作成するとき(例: DownloadManager.setRequirements()
)
上記の例をご覧ください。コマンドを 1 つずつ送信して動的に変更することもできます。
DownloadService
に追加します。
Kotlin
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService::class.java, requirements, /* foreground= */ false)
Java
// Set the download requirements. DownloadService.sendSetRequirements( context, MyDownloadService.class, requirements, /* foreground= */ false);
要件を満たしていないためにダウンロードを続行できない場合は、
Download.STATE_QUEUED
状態になります。満たされていないクエリをクエリすることもできます。
DownloadManager.getNotMetRequirements()
と併用します。
並列ダウンロードの最大数の設定
並列ダウンロードの最大数は、次の呼び出しによって設定できます。
DownloadManager.setMaxParallelDownloads()
。これは通常
上記の例のように DownloadManager
を作成します。
並列ダウンロードの最大数が原因でダウンロードを続行できない場合
すでに処理中の場合は、Download.STATE_QUEUED
状態になります。
ダウンロードのクエリ
DownloadManager
の DownloadIndex
に対して、すべての状態を照会できる
完了または失敗したダウンロードが含まれますDownloadIndex
DownloadManager.getDownloadIndex()
を呼び出して取得できます。このカーソルは、
すべてのダウンロードに対して反復処理を実行します。その後、次の呼び出しによって
DownloadIndex.getDownloads()
。または 1 回のダウンロードの状態は
クエリするには DownloadIndex.getDownload()
を呼び出します。
DownloadManager
には DownloadManager.getCurrentDownloads()
も用意されています。
現在のダウンロードの状態(未完了または失敗)のみを返します。この
メソッドは、通知やその他の UI コンポーネントを更新するときに役立ちます。
ダウンロードの進行状況やステータスを確認できます。
ダウンロードの再生
DownloadManager
にリスナーを追加すると、
ダウンロードの変更状態:
Kotlin
downloadManager.addListener( object : DownloadManager.Listener { // Override methods of interest here. } )
Java
downloadManager.addListener( new DownloadManager.Listener() { // Override methods of interest here. });
詳しくは、デモアプリの DownloadTracker
クラスの DownloadManagerListener
をご覧ください。
具体的な例を挙げます。
ダウンロードしたコンテンツの再生
ダウンロードしたコンテンツの再生は、オンライン コンテンツの再生と似ていますが、
データは、ネットワーク経由ではなく、ダウンロード Cache
から読み取られます。
ダウンロードしたコンテンツを再生するには、同じコマンドを使用して CacheDataSource.Factory
を作成します。
ダウンロードに使用された Cache
インスタンスを作成し、
プレーヤーのビルド時に DefaultMediaSourceFactory
を使用する:
Kotlin
// Create a read-only cache data source factory using the download cache. val cacheDataSourceFactory: DataSource.Factory = CacheDataSource.Factory() .setCache(downloadCache) .setUpstreamDataSourceFactory(httpDataSourceFactory) .setCacheWriteDataSinkFactory(null) // Disable writing. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory) ) .build()
Java
// Create a read-only cache data source factory using the download cache. DataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory() .setCache(downloadCache) .setUpstreamDataSourceFactory(httpDataSourceFactory) .setCacheWriteDataSinkFactory(null); // Disable writing. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build();
同じプレーヤー インスタンスを、ダウンロードされていないコンテンツの再生にも使用する場合
そのような事態を避けるために、CacheDataSource.Factory
を読み取り専用に構成する必要があります。
コンテンツをダウンロードすることもできます。
プレーヤーが CacheDataSource.Factory
で構成されると、
ダウンロードしたコンテンツにアクセスして再生できる。ダウンロードの再生は
対応する MediaItem
をプレーヤーに渡すだけです。MediaItem
Download.request.toMediaItem
を使用して Download
から取得できます。または、
DownloadRequest.toMediaItem
を使用して DownloadRequest
から直接取得します。
MediaSource の構成
上記の例では、ダウンロード キャッシュをすべての
MediaItem
秒。ダウンロードキャッシュを
プレーヤーに直接渡すことができる個別の MediaSource
インスタンス:
Kotlin
val mediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)) player.setMediaSource(mediaSource) player.prepare()
Java
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory) .createMediaSource(MediaItem.fromUri(contentUri)); player.setMediaSource(mediaSource); player.prepare();
アダプティブ ストリームのダウンロードと再生
アダプティブ ストリーム(DASH、SmoothStreaming、HLS など)には通常、 使用できます。同じコンテンツを含む複数のトラックが 画質の違い(SD、HD、4K 動画トラックなど)に対応しています。また、 同じタイプの複数のトラックに、異なるコンテンツ(複数の 音声トラックが異なる場合があります。
ストリーミング再生では、トラック セレクタを使用して、
トラックが再生されます。同様に、ダウンロードの場合、DownloadHelper
を使用して以下を行うことができます。
一時保存するトラックを選択できます。DownloadHelper
の一般的な使用例
手順は次のとおりです。
- いずれかの
DownloadHelper.forMediaItem
を使用してDownloadHelper
を作成する あります。ヘルパーを準備し、コールバックを待ちます。Kotlin
val downloadHelper = DownloadHelper.forMediaItem( context, MediaItem.fromUri(contentUri), DefaultRenderersFactory(context), dataSourceFactory ) downloadHelper.prepare(callback)
Java
DownloadHelper downloadHelper = DownloadHelper.forMediaItem( context, MediaItem.fromUri(contentUri), new DefaultRenderersFactory(context), dataSourceFactory); downloadHelper.prepare(callback);
- 必要に応じて、
getMappedTrackInfo
を使用して、デフォルトで選択されているトラックを確認します。 およびgetTrackSelections
、clearTrackSelections
を使用して調整します。replaceTrackSelections
、addTrackSelection
。 - 呼び出して、選択したトラックの
DownloadRequest
を作成します。getDownloadRequest
。このリクエストは、DownloadService
に渡して ダウンロードを追加します。 release()
を使用してヘルパーを解放します。
ダウンロードしたアダプティブ コンテンツを再生するには、プレーヤーを設定し、
前述のように、対応する MediaItem
を渡します。
MediaItem
をビルドする場合、MediaItem.localConfiguration.streamKeys
は次のようにする必要があります。
DownloadRequest
内のものと一致するように設定します。これにより、プレーヤーは
ダウンロードしたトラックのサブセットを再生できます。使用
Download.request.toMediaItem
と DownloadRequest.toMediaItem
を使用して、
この処理は MediaItem
が行います。