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

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

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

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

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

Media3 のいくつかのコンポーネントは、Player インターフェースを実装しています。たとえば、次のようなコンポーネントがあります。

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

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

Media3 の再生アーキテクチャ

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

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

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

プレーヤーの状態

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

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

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

変更をリッスンする

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

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

Kotlin

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

Java

Handler handler = new Handler(Looper.getMainLooper());
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 : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(...) // 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

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

  @Override
  protected State getState() {
    return new State.Builder()
      .setAvailableCommands(...) // 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_ITEMCOMMAND_SEEK_TO_NEXT_MEDIA_ITEM などのオペレーションをサポートします。

Player 実装を変更する

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