プレーヤー インターフェース

プレーヤーは、メディア アイテムの再生を容易にするアプリのコンポーネントです。Media3 の Player インターフェースは、一般的にプレーヤーによって処理される機能の概要を設定します。これには次のものが含まれます。

  • 再生、一時停止、シークなどの再生コントロールに影響する
  • 現在再生中のメディアのプロパティ(再生位置など)をクエリする
  • メディア アイテムの再生リスト/キューの管理
  • 再生プロパティ(シャッフル、リピート、速度、音量など)を構成する
  • 画面への動画のレンダリング

Media3 には、ExoPlayer という Player インターフェースの実装も用意されています。

コンポーネント間の共通インターフェース

Media3 のいくつかのコンポーネントは、Player インターフェースを実装しています。次に例を示します。

コンポーネント 説明と動作に関する注意事項
ExoPlayer メディア プレーヤー API と Player インターフェースのデフォルト実装。
MediaController MediaSession とやり取りして、再生コマンドを送信します。Player と MediaSession が、プレーヤーの UI が存在する Activity または Fragment とは別の Service にある場合は、MediaController を PlayerView や Player コンポーザブルなどの UI コンポーネントのプレーヤーとして割り当てることができます。再生メソッドとプレイリスト メソッドの呼び出しは、MediaSession を介して Player に送信されます。
MediaBrowser MediaController が提供する機能に加えて、MediaLibrarySession とやり取りして、利用可能なメディア コンテンツをブラウジングします。
SimpleBasePlayer 実装するメソッドの数を最小限に抑える Player 実装。MediaSession に接続するカスタム プレーヤーを使用する場合に便利です。
ForwardingSimpleBasePlayer 再生オペレーションを別の Player に転送すると同時に、SimpleBasePlayer と同じ一貫した動作のカスタマイズを可能にするように設計された SimpleBasePlayer サブクラス。このクラスを使用して、特定の再生オペレーションを抑制または変更します。
RemoteCastPlayer リモートの Cast レシーバー アプリで再生を制御するための Player 実装。
CastPlayer ローカルとリモートの両方のキャスト再生を制御するための Player 実装。

MediaSession は Player インターフェースを実装しませんが、作成時に Player が必要です。その目的は、他のプロセスまたはスレッドから Player へのアクセスを提供することです。

Media3 再生アーキテクチャ

Player にアクセスできる場合は、そのメソッドを直接呼び出して再生コマンドを発行する必要があります。MediaSession を実装することで、再生をアドバタイズし、外部ソースに再生コントロールを付与できます。これらの外部ソースは MediaController を実装します。これにより、メディア セッションへの接続と再生コマンド リクエストの発行が容易になります。

バックグラウンドでメディアを再生する場合は、フォアグラウンド サービスとして実行される MediaSessionService または MediaLibraryService 内にメディア セッションとプレーヤーを格納する必要があります。そうすることで、プレーヤーを、再生コントロールの UI を含むアプリの Activity から分離できます。この場合、メディア コントローラの使用が必要になることがあります。

Media3 再生コンポーネントがメディアアプリのアーキテクチャにどのように適合するかを示す図。
図 1: Player インターフェースは、Media3 のアーキテクチャで重要な役割を果たします。

プレーヤーの状態

Player インターフェースを実装するメディア プレーヤーの状態は、主に次の 4 つのカテゴリの情報で構成されます。

  1. 再生状態
  2. メディア アイテムのプレイリスト
    • 再生用の MediaItem インスタンスのシーケンス。
    • getCurrentTimeline() で取得する
    • Player インスタンスは、MediaItem の追加や削除などのプレイリスト操作メソッドと、getCurrentMediaItem() などの便利なメソッドを提供できます。
  3. 再生/一時停止のプロパティ。例:
    • playWhenReady: ユーザーがメディアの再生を希望しているか、一時停止のままにすることを希望しているかを示します。
    • 再生抑制の理由: playWhenReady が true の場合でも、再生が抑制されている理由(該当する場合)を示します。
    • isPlaying: プレーヤーが現在再生中かどうかを示します。再生状態が STATE_READY、playWhenReady が true、再生が抑制されていない場合にのみ true になります。
  4. 再生位置。以下が含まれます。

さらに、Player インターフェースを使用すると、利用可能なトラック、メディア メタデータ、再生速度、音量、その他の再生の補助プロパティにアクセスできます。

変更をリッスンする

Player.Listener を使用して、Player の変更をリッスンします。リスナーの作成方法と使用方法について詳しくは、プレーヤー イベントに関する ExoPlayer のドキュメントをご覧ください。

リスナー インターフェースには、通常の再生の進行状況を追跡するコールバックは含まれていません。再生の進行状況を継続的にモニタリングするには(進行状況バーの UI を設定する場合など)、適切な間隔で現在の位置をクエリする必要があります。

Kotlin

fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs,
  )

Java

boolean checkPlaybackPosition(long delayMs) {
  return handler.postDelayed(
      () -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
      },
      delayMs);
}

再生を操作する

Player インターフェースには、状態を操作して再生を制御するためのさまざまな方法が用意されています。

カスタム Player の実装

カスタム プレーヤーを作成するには、Media3 に含まれている SimpleBasePlayer を拡張します。このクラスは、Player インターフェースの基本実装を提供し、実装する必要があるメソッドの数を最小限に抑えます。

まず、getState() メソッドをオーバーライドします。このメソッドは、呼び出されたときに、次のような現在のプレーヤーの状態を読み込む必要があります。

  • 使用可能なコマンドのセット
  • 再生プロパティ(再生状態が STATE_READY のときにプレーヤーが再生を開始するかどうか、現在再生中のメディア アイテムのインデックス、現在のアイテム内の再生位置など)

Kotlin

class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build()
  }
}

Java

private static final class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
        .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle
        // Configure additional playback properties
        .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
        .setCurrentMediaItemIndex(0)
        .setContentPositionMs(0)
        .build();
  }
}

SimpleBasePlayer は、状態値の有効な組み合わせで State が作成されるようにします。また、リスナーを処理し、リスナーに状態の変化を通知します。状態の更新を手動でトリガーする必要がある場合は、invalidateState() を呼び出します。

getState() メソッド以外に実装する必要があるのは、プレーヤーが利用可能であると宣言するコマンドに使用されるメソッドのみです。実装する機能に対応する、オーバーライド可能なハンドラ メソッドを見つけます。たとえば、handleSeek() メソッドをオーバーライドして、COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM や COMMAND_SEEK_TO_NEXT_MEDIA_ITEM などのオペレーションをサポートします。

Player の実装を変更する

完全にカスタムの Player を作成する代わりに、ForwardingSimpleBasePlayer を使用して既存の Player の状態と動作を変更できます。詳しくは、カスタマイズ ページのガイドをご覧ください。