プレーヤーは、メディア アイテムの再生を容易にするアプリのコンポーネントです。Media3 の Player
インターフェースは、一般的にプレーヤーによって処理される機能の概要を設定します。これには、次のものがあります。
- 再生、一時停止、シークなどの再生操作に影響する
- 現在再生中のメディアのプロパティ(再生位置など)をクエリする
- メディア アイテムの再生リスト/キューの管理
- 再生プロパティの設定(シャッフル、繰り返し、速度、音量など)
- 画面への動画のレンダリング
Media3 には、Player
インターフェースの実装(ExoPlayer
)も用意されています。
コンポーネント間の共通インターフェース
Media3 のいくつかのコンポーネントは、Player インターフェースを実装しています。たとえば、次のようなコンポーネントがあります。
コンポーネント | 説明と動作に関するメモ |
---|---|
ExoPlayer |
メディア プレーヤー API と Player インターフェースのデフォルト実装。 |
MediaController |
MediaSession とやり取りして再生コマンドを送信します。Player と MediaSession が、プレーヤーの UI が存在する Activity または Fragment とは別の Service にある場合は、MediaController を PlayerView UI のプレーヤーとして割り当てることができます。再生とプレイリストのメソッド呼び出しは、MediaSession を介して Player に送信されます。 |
MediaBrowser |
MediaController が提供する機能に加えて、MediaLibrarySession とやり取りして、利用可能なメディア コンテンツをブラウジングします。
|
ForwardingPlayer |
メソッド呼び出しを別の Player に転送する Player 実装。このクラスを使用すると、それぞれのメソッドをオーバーライドして、特定のオペレーションを抑制または変更できます。 |
SimpleBasePlayer |
実装するメソッドの数を最小限に抑える Player 実装。カスタム プレーヤーを使用して MediaSession に接続する場合に便利です。
|
CastPlayer |
Cast レシーバー アプリと通信する Player の実装。動作は、基盤となる Cast セッションによって異なります。 |
MediaSession
は Player
インターフェースを実装していませんが、作成するときに Player
が必要です。その目的は、他のプロセスまたはスレッドから Player
にアクセスできるようにすることです。
Media3 の再生アーキテクチャ
Player
にアクセスできる場合は、そのメソッドを直接呼び出して再生コマンドを実行する必要があります。MediaSession
を実装すると、再生をアドバタイズし、外部ソースに再生コントロールを付与できます。これらの外部ソースは MediaController
を実装します。これにより、メディア セッションへの接続と再生コマンド リクエストの発行が容易になります。
バックグラウンドでメディアを再生する場合は、メディア セッションとプレーヤーを、フォアグラウンド サービスとして実行される MediaSessionService
または MediaLibraryService
内に配置する必要があります。そうすることで、再生コントロールの UI を含むアプリ内のアクティビティからプレーヤーを分離できます。この場合、メディア コントローラを使用する必要が生じることがあります。
プレーヤーの状態
Player
インターフェースを実装するメディア プレーヤーの状態は、主に次の 4 つのカテゴリの情報で構成されます。
- 再生状態
getPlaybackState()
を使用して取得します。- インターフェースで定義された状態値は、
STATE_IDLE
、STATE_BUFFERING
、STATE_READY
、STATE_ENDED
です。
- メディア アイテムの再生リスト
- 再生用の
MediaItem
インスタンスのシーケンス。 getCurrentTimeline()
で取得Player
インスタンスは、MediaItem
の追加や削除などの再生リスト操作メソッドと、getCurrentMediaItem()
などのコンビニエンス メソッドを提供できます。
- 再生用の
- 再生/一時停止のプロパティ(次に例を示します)。
playWhenReady
: ユーザーがメディアを可能な限り再生するか、一時停止したままにするかを示す- 再生の抑制理由: 再生が抑制される理由(
playWhenReady
がtrue
の場合でも該当する場合)。 isPlaying
: プレーヤーが現在再生中かどうか。再生状態がSTATE_READY
、playWhenReady
がtrue
、再生が抑制されていない場合のみtrue
になります。
- 再生位置(次に例を示します)。
- 現在のメディア アイテム インデックス: 再生リスト内の現在の
MediaItem
のインデックス。 isPlayingAd
: 挿入された広告が再生されているかどうかを示します。- 現在の再生位置: 現在の
MediaItem
または挿入された広告内の現在の再生位置。
- 現在のメディア アイテム インデックス: 再生リスト内の現在の
また、Player
インターフェースでは、利用可能なトラック、メディア メタデータ、再生速度、音量などの再生の補助プロパティにアクセスできます。
変更をリッスンする
Player.Listener
を使用して、Player
の変更をリッスンします。リスナーの作成方法と使用方法について詳しくは、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
インターフェースには、状態を操作して再生を制御するためのさまざまな方法が用意されています。
play()
、pause()
、prepare()
、stop()
などの基本的な再生コントロール。addMediaItem()
やremoveMediaItem()
などの再生リスト オペレーション。- シーク: 現在のアイテムまたは位置を変更します。
- リピート モードとシャッフル モードを設定します。
- トラック選択の設定を更新します。
- 再生速度を設定します。
カスタム 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_ITEM
や COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
などのオペレーションをサポートします。