DefaultPreloadManager を作成して構成する

このページでは、選択した戦略に基づいてアプリのメディア コンテンツをプリロードする DefaultPreloadManager を作成する方法について説明します。

BasePreloadManager 抽象クラスに基づくプリロード マネージャーを使用すると、選択した条件でコンテンツの優先順位を付けることができます。このドキュメントでは、派生クラス DefaultPreloadManager の使用方法について説明します。このクラスでは、各メディア アイテムがリスト内の位置(動画カルーセルの位置など)を表す整数でランク付けされます。プリロード マネージャーは、ユーザーが現在再生しているアイテムに近いアイテムを優先して読み込みます。これにより、ユーザーが別のアイテムに移動した場合、新しいアイテムをすぐに再生できます。

DefaultPreloadManager のインスタンスを作成する 3 つの手順は次のとおりです。

  • TargetPreloadStatusControl を定義します。これにより、プリロード マネージャーは、メディア アイテムの読み込み準備が完了しているか、また読み込み量をどのくらいにするかのクエリを実行できるようになります。
  • プリロード マネージャーの作成とアプリの ExoPlayer オブジェクトの作成に使用するビルダーを作成します。
  • ビルダーの build() メソッドを呼び出して、ビルダーを使用してプリロード マネージャーを作成します。

ターゲット プリロード ステータス コントロールを作成する

DefaultPreloadManager.Builder を作成するときに、定義したターゲットのプリロード ステータス制御オブジェクトを渡します。このオブジェクトは TargetPreloadStatusControl インターフェースを実装します。プリロード マネージャーがメディアのプリロードの準備をしているとき、ステータス コントロールの getTargetPreloadStatus() メソッドを呼び出して、メディア アイテムのコンテンツを準備、読み込み、キャッシュ保存するかどうかを判断します。プリロードでは、メディアデータがプレーヤーのメモリ内バッファに直接読み込まれ、すぐに再生できるようになります。一方、キャッシュ保存では、メディアデータが永続ディスク キャッシュに保存され、プレーヤーのメモリが節約されます。ステータス コントロールは、次のいずれかのステータス コードで応答できます。

  • STAGE_SPECIFIED_RANGE_LOADED: プリロード マネージャーは、指定された開始位置から指定された期間(ミリ秒単位)のコンテンツをプレーヤーのインメモリ バッファに読み込む必要があります。
  • STAGE_SPECIFIED_RANGE_CACHED: プリロード マネージャーは、指定された開始位置から指定された期間(ミリ秒単位)のコンテンツをディスク キャッシュにキャッシュ保存する必要があります。
  • STAGE_TRACKS_SELECTED: プリロード マネージャーは、コンテンツ トラックの情報を読み込んで処理し、トラックを選択する必要があります。プリロード マネージャーは、まだコンテンツの読み込みを開始すべきではありません。
  • STAGE_SOURCE_PREPARED: プリロード マネージャーはコンテンツ ソースを準備する必要があります。たとえば、コンテンツのメタデータが別のマニフェスト ファイルにある場合、プリロード マネージャーはそのマニフェストを取得して解析する可能性があります。
  • null: プリロード マネージャーは、そのメディア アイテムのコンテンツやメタデータを読み込むべきではありません。

各メディア アイテムで読み込むコンテンツの量を決定する戦略が必要です。この例では、現在再生中のアイテムに最も近いアイテムのコンテンツがさらに読み込まれます。ユーザーがインデックス n のコンテンツを再生している場合、コントローラは次のコードを返します。

  • インデックス n+1(次のメディア アイテム): デフォルトの開始位置から 3,000 ミリ秒(3 秒)を読み込みます
  • インデックス n-1(前のメディア アイテム): デフォルトの開始位置から 1,000 ミリ秒(1 秒)を読み込みます
  • 範囲 n-2n+2 の他のメディア アイテム: PreloadStatus.TRACKS_SELECTED を返します
  • 範囲 n-4n+4 の他のメディア アイテム: PreloadStatus.SOURCE_PREPARED を返します
  • その他のすべてのメディア アイテムについては、null を返します

class MyTargetPreloadStatusControl(var currentPlayingIndex: Int = 0) :
  TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> {

  override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus {
    if (index - currentPlayingIndex == 1) { // next track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (index - currentPlayingIndex == -1) { // previous track
      // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and
      // suggest loading 3000ms from the default start position
      return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L)
    } else if (abs(index - currentPlayingIndex) == 2) {
      // return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED
    } else if (abs(index - currentPlayingIndex) <= 4) {
      // return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED
      return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED
    }
    return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED
  }
}

コードに関する主なポイント

  • MyTargetPreloadStatusControl のインスタンスは、作成時にプリロード マネージャー ビルダーに渡します。
  • currentPlayingIndex には、現在再生中のメディア アイテムのインデックスが格納されます。この値を最新の状態に保つのはアプリの役割です。
  • プリロード マネージャーがコンテンツを読み込む準備ができたら、getTargetPreloadStatus を呼び出し、対応するメディア アイテムに指定したランキング情報を渡します。DefaultPreloadManager の場合、ランキング情報はカルーセル内のアイテムの位置を指定する整数です。このメソッドは、そのインデックスと現在選択されているアイテムのインデックスを比較して、返すコードを選択します。

プリロード マネージャーを作成する

プリロード マネージャーを作成するには、DefaultPreloadManager.Builder が必要です。このビルダーは、現在のコンテキストとアプリのターゲット プリロード ステータス制御で構成されています。すべてのデフォルト構成でプリロード マネージャーを作成できます。

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
val preloadManager = preloadManagerBuilder.build()

ビルダーには、プリロード マネージャーのカスタム コンポーネントを設定するためのセッター メソッドも用意されています。

たとえば、DefaultPreloadManager のすべてのプリロード メディアソースのターゲット合計バッファ バイト数をカスタマイズして、プリロードされたデータがその上限を超えないようにすることができます。この上限は、カスタム DefaultLoadControl.Builder でプレーヤー名 "preload" を使用して setPlayerTargetBufferBytes(String, int) を使用して構成し、そのインスタンスをプリロード マネージャー ビルダーに渡すことができます。

val targetPreloadStatusControl = MyTargetPreloadStatusControl()
val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl)

preloadManagerBuilder.setLoadControl(
  DefaultLoadControl.Builder()
    .setPlayerTargetBufferBytes("preload", 128 * 1024 * 1024) // 128 MiB
    .build()
)
val preloadManager = preloadManagerBuilder.build()

ビルダーのセッター メソッドは基本的にカスタマイズには必須ではありませんが、メディア アイテムをディスクにキャッシュ保存する場合は、setCache() を呼び出して Cache でビルダーを構成する必要があります。キャッシュが構成されていない場合、メディア アイテムをキャッシュに保存しようとすると IllegalStateException が発生します。

プリロードされたメディア アイテムを再生する ExoPlayer を作成する

ビルダーは、プリロード マネージャーの作成だけでなく、アプリがコンテンツの再生に使用する ExoPlayer オブジェクトの作成にも使用します。これにより、ExoPlayer はプリロード マネージャーとコンポーネントを正しく共有できます。ExoPlayer の再生固有の構成は、それらの構成が設定された ExoPlayer.Builder インスタンスを渡すことで設定できます。

// Direct creation
val exoPlayer = preloadManagerBuilder.buildExoPlayer()

// Creation with custom playback specific configurations
val skipSilenceExoPlayerBuilder = ExoPlayer.Builder(context).setSkipSilenceEnabled(true)
val skipSilenceExoPlayer = preloadManagerBuilder.buildExoPlayer(skipSilenceExoPlayerBuilder)