Screenshot: YouTube Android アプリ
ExoPlayer は、Android の低レベル メディア API の上に構築されたアプリ レベルのメディア プレーヤーです。 ExoPlayer には、Android に組み込まれた MediaPlayer よりも多くの利点があります。 MediaPlayer と同じメディア フォーマットの多くに加え、DASH や SmoothStreaming などのアダプティブ フォーマットをサポートしています。 ExoPlayer は、高度なカスタマイズと拡張が可能で、多くの高度なユースケースに対応できます。
- 前提条件
- 作業内容
- 必要なもの
- コードの入手
- ディレクトリ構造
- 初期プロジェクトのインポート
- app/build.gradle
- Add ExoPlayer dependency
- player-lib/build.ExoPlayer モジュールにある build.gradle file of a dependencies file of the dependencies module.Above.ExoPlayer モジュールを開きます。gradle
- Add the PlayerView element
- activity_player.xml
- PlayerActivity.java
- Create an ExoPlayer
- PlayerActivity.java
- メディア アイテムの作成
- PlayerActivity.java
- Playing nice with the Activity lifecycle
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- 最終準備
- PlayerActivity.java
- Play audio
- Test the activity lifecycle
- Play video
- PlayerActivity.java
- PlayerActivity.java
- Adaptive track selection
- PlayerActivity.java
- Build an adaptive MediaItem
- PlayerActivity.java
- Other adaptive streaming formats
- Listen up
- PlayerActivity.Listener を使用して、プレーヤーがどの状態にあるかをログに記録します。java
- PlayerActivity.java
- PlayerActivity.java
- Register your listener
- PlayerActivity.java
- PlayerActivity.java
- さらに深く
- activity_player.xml
- activity_player.xml
- Customize the behaviour
- activity_player.xml
- 外見のカスタマイズ
- activity_player.xml
- custom_player_control_view.xml
- custom_player_control_view.xml
- デフォルト スタイルをオーバーライドする
- activity_player.xml
- Learn more
前提条件
- Moderate knowledge of Android development and Android Studio
作業内容
-
SimpleExoPlayer
インスタンスを作成し、さまざまなソースからメディアを準備および再生する。 - ExoPlayer をアプリのアクティビティ ライフサイクルに統合し、単一ウィンドウまたはマルチウィンドウ環境でのバックグラウンド化、フォアグラウンド化、および再生の再開をサポートします。
- 利用可能な帯域幅にメディア品質を適応させるアダプティブ ビデオ ストリームを再生する。
- 再生状態を監視するイベント リスナーを登録し、リスナーが再生品質の測定に使用される方法を説明する。
- 標準の ExoPlayer UI コンポーネントを使用し、アプリのスタイルに合わせてカスタマイズします。
必要なもの
- Android Studio バージョン 3.5 以上
- JellyBean (4.1) 以上、マルチウィンドウに対応しているので Nougat (7.1) 以上の Android 機器。
コードの入手
はじめに、Android Studioプロジェクトをダウンロードします:
Download zip
または、GitHubリポジトリをcloneします。
git clone https://github.com/googlecodelabs/exoplayer-intro.git
ディレクトリ構造
クローンまたは解凍すると、ルート フォルダー (exoplayer-intro
) に、このコード ラボの各ステップのフォルダーと、必要なすべてのリソースが格納されます:
/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-00/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-01/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-02/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-03/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-04
exoplayer-codelab-N
フォルダー (N
は 00
から 04
) にはこのコード ラボでの各ステップの望ましい最終状態が含まれます。 これらはスタンドアロンの Android Studio プロジェクトで、それぞれインポートすることができます。
初期プロジェクトのインポート
- Start Android Studio.
- Choose File > New > Import Project*.*
- Import the initial project from
exoplayer-codelab-00
.
Screenshot.Of the Android Project Project.Import the initial Project of the Android Studio: インポート時のプロジェクト構造
ビルドが終了すると、app
モジュール(アプリケーション型)とplayer-lib
モジュール(ライブラリ型)の2つのモジュールが表示されます。 app
モジュールは実際には空で、マニフェストのみを持っています。 player-lib
モジュールのすべては、アプリが app/build.gradle
.
app/build.gradle
で gradle 依存関係を使用してビルドされるときにマージされます。 別のライブラリ モジュールに保持する理由は、モバイルと Android TV など、異なるプラットフォームを対象とする APK 間で共有できるようにするためです。 また、ユーザーが必要とするときにのみメディア再生機能をインストールできる Dynamic Delivery などの機能を利用することもできます。
- アプリの展開と実行ですべてがうまくいっていることを確認します。 アプリは黒い背景で画面を埋めるはずです。
Screenshot: Blank app running
Add ExoPlayer dependency
ExoPlayer は、GitHub でホストされているオープン ソース プロジェクトです。 各リリースは、Android Studio と Gradle で使用されるデフォルトのパッケージ リポジトリの 1 つである jCenter を通して配布されます。 各リリースは、次の形式の文字列で一意に識別されます:
com.google.android.exoplayer:exoplayer:rX.X.X
あなたは、そのクラスとUIコンポーネントをインポートすることによって、あなたのプロジェクトにExoPlayerを追加することができます。 これはかなり小さく、含まれる機能やサポートされる形式に応じて、約 70 ~ 300kB の縮小されたフットプリントを持っています。 ExoPlayer ライブラリはモジュールに分割されており、開発者は必要な機能のみをインポートすることができます。 ExoPlayer のモジュール構造の詳細については、ExoPlayer モジュールの追加を参照してください。
- Open the
player-lib
module. - Add the following lines to the
dependencies
section and sync the project.
player-lib/build.ExoPlayer モジュールにある build.gradle
file of a dependencies
file of the dependencies
module.Above.ExoPlayer モジュールを開きます。gradle
dependencies { implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'implementation 'com.google.android.exoplayer:exoplayer-dash:2.12.0'implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'}
Add the PlayerView element
- Open the layout resource file
activity_player.xml
from theplayer-lib
module. - Place the cursor inside the
FrameLayout
element. - 入力開始
<PlayerView
and let Android Studio autocomplete thePlayerView
element.Authorized.を追加します。 -
width
とheight
にはmatch_parent
を使用します。 - IDを
video_view
と宣言します。
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
今後、このUI要素をビデオビューと呼びます。
-
PlayerActivity
では、ビデオ ビューを見つけて、アクティビティのonCreate
メソッドで適切に設定する必要があります。
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
- あなたの
PlayerActivity
クラスにplayerView
メンバー フィールドを追加してください。 ビューのタイプがPlayerView
.
Note: Android Studio のクイックフィックス機能を使用すると、メンバーフィールドを自動的に追加することができます。 デフォルトの
View
ではなく、
PlayerView
にタイプを設定するのを忘れないようにしてください。 メンバー フィールドを作成するクイック フィックス メニュー
Create an ExoPlayer
ストリーミング メディアを再生するには、ExoPlayer
オブジェクトが必要です。 最も簡単な作成方法は SimpleExoPlayer.Builder
クラスを使用することです。
SimpleExoPlayer
は便利な ExoPlayer
インターフェイスの多目的実装です。
プライベートメソッド initializePlayer
を追加して SimpleExoPlayer
を作成します。
PlayerActivity.java
private SimpleExoPlayer player;private void initializePlayer() { player = new SimpleExoPlayer.Builder(this).build(); playerView.setPlayer(player);}
コンテキストを使って SimpleExoPlayer.Builder
を作成し、build
を呼び出して SimpleExoPlayer
オブジェクトを作成します。 これは player
に代入され、メンバーフィールドとして宣言する必要があります。 playerView.setPlayer
を使用して、player
を対応するビューにバインドします。
メディア アイテムの作成
ここで player
は再生するためのコンテンツを必要とします。 このために、MediaItem
を作成します。
MediaItem
を作成する最も簡単な方法は、メディアファイルのURIを受け入れるMediaItem.fromUri
を使用することです。 player.setMediaItem
を使用して player
に MediaItem
を追加します。
-
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}
R.string.media_url_mp3
は strings.xml
で https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 として定義されているので注意してください。
Playing nice with the Activity lifecycle
Our player
can possess the lot of resources including memory, CPU, network connections and hardware codecs. これらのリソースの多くは不足しており、特にハードウェア コーデックは 1 つしかない場合があります。
別の言い方をすると、プレーヤーのライフサイクルはアプリのライフサイクルに関連付ける必要があります。 これを実装するには、PlayerActivity
の 4 つのメソッドをオーバーライドする必要があります。
-
PlayerActivity
を開いた状態で、[コード] メニュー > [メソッドのオーバーライド]… をクリックします。 - API レベルに応じて、
onStart
またはonResume
コールバックでプレーヤーを初期化します。
PlayerActivity.java
@Overridepublic void onStart() { super.onStart(); if (Util.SDK_INT >= 24) { initializePlayer(); }}@Overridepublic void onResume() { super.onResume(); hideSystemUi(); if ((Util.SDK_INT < 24 || player == null)) { initializePlayer(); }}
Android API レベル 24 以上ではマルチウィンドウがサポートされます。 アプリは表示されますが、分割ウィンドウ モードではアクティブではないので、onStart
でプレーヤーを初期化する必要があります。 Android API レベル 24 以下では、リソースを取得するまでできるだけ待つ必要があるため、onResume
まで待ってからプレーヤーを初期化します。
-
hideSystemUi
メソッドを追加します。
PlayerActivity.java
@SuppressLint("InlinedApi")private void hideSystemUi() { playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);}
hideSystemUi
は onResume
で呼ばれるヘルパーメソッドで、フルスクリーン体験ができるようにするためのメソッドです。
-
onPause
とonStop
でreleasePlayer
(まもなく作成)でリソースを解放します。
PlayerActivity.java
@Overridepublic void onPause() { super.onPause(); if (Util.SDK_INT < 24) { releasePlayer(); }}@Overridepublic void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { releasePlayer(); }}
APIレベル24以下では、onStop
が呼ばれる保証はないので、できるだけ早くonPause
でプレイヤーを解放しなければいけません。 API Level24以上(マルチ、スプリットウィンドウモードが登場)では、onStop
が呼び出されることが保証されています。 一時停止状態では、アクティビティはまだ表示されているので、onStop
までプレーヤーを解放するのを待ちます。
ここで、プレーヤーのリソースを解放して破棄する releasePlayer
メソッドを作成する必要があります。java
private boolean playWhenReady = true;private int currentWindow = 0;private long playbackPosition = 0;private void releasePlayer() { if (player != null) { playWhenReady = player.getPlayWhenReady(); playbackPosition = player.getCurrentPosition(); currentWindow = player.getCurrentWindowIndex(); player.release(); player = null; }}
Player を解放して破棄する前に、次の情報を保存します。
- Play/pause state using
getPlayWhenReady
. - Current playback position using
getCurrentPosition
. - Current window index using
getCurrentWindowIndex
.getCurrentWindowIndex
. ウィンドウについて詳しくは、タイムライン.
これにより、ユーザーが中断したところから再生を再開することができます。
最終準備
あとは、初期化時に releasePlayer
で保存したステート情報をプレーヤに供給するだけです。
-
initializePlayer
に以下を追加します:
PlayerActivity.java
private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}
ここで、
-
setPlayWhenReady
再生用のすべてのリソースが取得されると同時に再生を開始するかどうかをプレイヤーに指示します。playWhenReady
は最初はtrue
なので、アプリを最初に実行したときに自動的に再生が始まります。 -
seekTo
は、特定のウィンドウ内の特定の位置にシークすることをプレイヤーに指示します。currentWindow
とplaybackPosition
は両方ともゼロに初期化され、アプリを最初に実行したときに再生が最初から始まります。 -
prepare
はプレーヤーに再生に必要なすべてのリソースを取得するように指示します。
Play audio
最後に、完了しました!
prepare
は、再生するために必要なリソースをすべて取得するように指示しています。 アプリを起動して MP3 ファイルを再生し、埋め込まれたアートワークを確認します。
スクリーンショット。
Test the activity lifecycle
Test the app works in all the different states of the activity lifecycle.
- Start another app and put your app in the foreground again.The app playing a single track.
App Store では、アプリを起動し、埋め込まれたアートワークを見ることができます。 正しい位置で再開されますか。
- アプリを一時停止し、バックグラウンドに移動して、再びフォアグラウンドに移動します。 一時停止状態でバックグラウンドにしたとき、一時停止状態に固執しますか。
- アプリを回転させます。 縦から横へ、そしてまた横へと向きを変えた場合、どのように動作しますか?
Play video
動画を再生したい場合は、メディア項目の URI を MP4 ファイルに変更するだけで、簡単に再生できます。
-
initializePlayer
の URI をR.string.media_url_mp4
に変更します。 - アプリを再度起動し、ビデオ再生でバックグラウンド化した後の動作もテストします。
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }
PlayerView
がすべてを行います。 アートワークの代わりに、ビデオはフルスクリーンでレンダリングされます。
Screenshot: ビデオを再生しているアプリ。
You rock! ライフサイクル管理、保存された状態、および UI コントロールを完備した、Android でのフルスクリーン メディア ストリーミング用アプリを作成したのです!
現在のアプリは単一のメディア ファイルを再生しますが、複数のメディア ファイルを次々に再生したい場合はどうしたらよいでしょうか。 そのためには、プレイリストが必要です。
プレイリストは、addMediaItem
を使用して player
にさらに MediaItem
を追加することによって作成することができます。 これにより、シームレスな再生が可能になり、バッファリングはバックグラウンドで処理されるため、ユーザーはメディア項目を変更する際にバッファリング スピナーを見ることはありません。
-
initializePlayer
に次のコードを追加します:
PlayerActivity.java
private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }
プレーヤー コントロールがどう動作しているかを確認する。 と を使用してメディア項目のシーケンスをナビゲートできます。
Screenshot: Next および Previous ボタンを表示する再生コントロール
これはかなり便利です! 詳細については、Media Items と Playlist の開発者向けドキュメント、および Playlist API に関するこの記事を参照してください。
Adaptive ストリーミングは、利用可能なネットワーク帯域幅に基づいてストリームの品質を変化させることにより、メディアをストリーミングするための手法です。 これにより、ユーザーは帯域幅が許容する最高品質のメディアを体験できます。
通常、同じメディア コンテンツは、異なる品質 (ビットレートと解像度) を持つ複数のトラックに分割されます。 プレーヤーは、使用可能なネットワーク帯域幅に基づいてトラックを選択します。
各トラックは、通常 2 秒から 10 秒の間の所定の持続時間のチャンクに分割されます。 これにより、利用可能な帯域幅の変化に応じて、プレーヤーはトラックをすばやく切り替えることができます。
Adaptive track selection
Adaptive ストリーミングの中心は、現在の環境に最も適したトラックを選択することです。 アダプティブ トラック セレクションを使用して、アダプティブ ストリーミング メディアを再生するようにアプリを更新します。
-
initializePlayer
を次のコードで更新します。
PlayerActivity.java
private void initializePlayer() { if (player == null) { DefaultTrackSelector trackSelector = new DefaultTrackSelector(this); trackSelector.setParameters( trackSelector.buildUponParameters().setMaxVideoSizeSd()); player = new SimpleExoPlayer.Builder(this) .setTrackSelector(trackSelector) .build(); } // Remove or comment out. // player = new SimpleExoPlayer.Builder(this).build(); }
最初に、メディア アイテムでトラックを選択する役割を持つ DefaultTrackSelector
を作成します。 次に、標準画質以下のトラックのみを選択するよう trackSelector
に指示します。これは、品質を犠牲にしてユーザーのデータを保存する良い方法です。 最後に、trackSelector
をビルダーに渡し、SimpleExoPlayer
インスタンスを構築する際に使用します。
Build an adaptive MediaItem
DASH は広く使用されているアダプティブ ストリーミング フォーマットです。 DASH コンテンツをストリーミングするには、前回と同様に MediaItem
を作成する必要があります。
これは、fromUri
はファイル拡張子を使用して基礎となるメディア形式を決定しますが、DASH URI にはファイル拡張子がないため、MediaItem
を構築するときに APPLICATION_MPD
の MIME タイプを指定しなければならないからです。
-
initializePlayer
を次のように更新します。
PlayerActivity.java
private void initializePlayer() { // Replace this line MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp4)); // With this MediaItem mediaItem = new MediaItem.Builder() .setUri(getString(R.string.media_url_dash)) .setMimeType(MimeTypes.APPLICATION_MPD) .build(); // Also remove the following lines MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem);}
- アプリを再起動すると、DASH によるアダプティブ ビデオ ストリーミングが実行されていることが確認できます。 ExoPlayer ではとても簡単です!
Other adaptive streaming formats
HLS (MimeTypes.APPLICATION_M3U8
) と SmoothStreaming (MimeTypes.APPLICATION_SS
) は他の一般的なアダプティブ ストリーミング形式で、両方とも ExoPlayer でサポートされています。 他のアダプティブ メディア ソースの構築に関する詳細については、ExoPlayer デモ アプリを参照してください。
これまでの手順で、プログレッシブおよびアダプティブ メディア ストリームをストリームする方法について学びました。 ExoPlayer は、舞台裏で次のような多くの作業を行っています。
- Allocating memory
- Downloading container files
- Extracting metadata from container
- Decoding data
Rendering video, audio, and text to screen and loudspeakers
ExoPlayer が実行時に何を行うかを知っていれば、ユーザーに対してプレイバック体験を理解し改善できることがあります。
- 再生がバッファリング状態になったときにローディングスピナーを表示する
- トラックが終了したときに “watch next” オプションのオーバーレイを表示する
ExoPlayer には、有用なイベントのコールバックを提供するリスナー インターフェースがいくつか備わっています。
Listen up
-
PlayerActivity
でPlaybackStateListener
型のプライベート メンバーを宣言します。 - Create a
TAG
constant, which you use for logging later.
PlayerActivity.Listener を使用して、プレーヤーがどの状態にあるかをログに記録します。java
private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
-
onCreate
の先頭にあるplaybackStateListener
をインスタンス化します(まだコンパイルできませんが、すぐに修正します)。
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
- 内部クラス
PlaybackStateListener
を自動的に作成するにはクイックフィックスを使います。
Screenshot: 不足しているクラスを作成するためのクイック修正メニュー
-
Player.EventListener
インターフェイスを実装します。 これは、エラーや再生状態の変更など、重要なプレーヤーのイベントを通知するために使用されます。 - Override
onPlaybackStateChanged
by adding the following code:
PlayerActivity.java
private class PlaybackStateListener implements Player.EventListener { @Override public void onPlaybackStateChanged(int playbackState) { String stateString; switch (playbackState) { case ExoPlayer.STATE_IDLE: stateString = "ExoPlayer.STATE_IDLE -"; break; case ExoPlayer.STATE_BUFFERING: stateString = "ExoPlayer.STATE_BUFFERING -"; break; case ExoPlayer.STATE_READY: stateString = "ExoPlayer.STATE_READY -"; break; case ExoPlayer.STATE_ENDED: stateString = "ExoPlayer.STATE_ENDED -"; break; default: stateString = "UNKNOWN_STATE -"; break; } Log.d(TAG, "changed state to " + stateString); }}
onPlaybackStateChanged
is called when the playback state changed.Java.Java
private class PlaybackStateListener implements Player.EventListener { @Override public void onPlaybackStateChanged(int playbackState) { String stateString; switch (playbackState) { case ExoPlayer.STATE_IDLE: stateString = "ExoPlayer.STATE_IDLE -"; break; case ExoPlayer.STATE_BUFFERING: stateString = "ExoPlayer.STATE_BUFFERING -"; break; case ExoPlayer.STATE_READY: stateString = "ExoPlayer.STATE_READY -"; break; case ExoPlayer.STATE_ENDED: stateString = "ExoPlayer.STATE_ENDED -"; break; default: stateString = "UNKNOWN_STATE -"; break; } Log.d(TAG, "changed state to " + stateString); }}
PlayerActivity.java>
onPlaybackStateChanged
は、再生状態が変更されたときに呼び出されます。 新しい状態は playbackState
パラメータで与えられます。
プレーヤーは次の4つの状態のうちの1つになることができます:
State |
Description |
|
プレーヤーが初期状態になりましたがまだ準備されていない状態です。 |
|
|
|
|
|
プレーヤーがメディアの再生を完了しました。 |
Register your listener
コールバックが呼ばれるために、playbackStateListener
をプレーヤーに登録する必要があります。 initializePlayer
.
- Register the listener before the play is prepared.
PlayerActivity.java
private void initializePlayer() { if (player == null) { player.addListener(playbackStateListener); player.prepare();}
Again, you need to tidy up to avoid dangling references from the player which may cause a memory leak.プレーヤーからの参照で、メモリーリークを起こさないようにします。
- releasePlayer:
PlayerActivity.java
private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
- logcat を開いてアプリを実行。
- UI コントロールを使って再生を模索、一時停止、再開してください。 ログに再生状態の変化が見られるはずです。
さらに深く
ExoPlayer は、ユーザーの再生体験を理解するのに役立つ、他の多くのリスナーを提供します。 オーディオとビデオ用のリスナー、およびすべてのリスナーからのコールバックを含む AnalyticsListener
があります。 最も重要なメソッドは次のとおりです。
-
onRenderedFirstFrame
は、ビデオの最初のフレームがレンダリングされるときに呼び出されます。 これを使用して、ユーザーが画面上に意味のあるコンテンツを表示するために待たなければならなかった時間を計算することができます。 -
onDroppedVideoFrames
は、ビデオ フレームがドロップされたときに呼び出されます。 ドロップされたフレームは、再生が不安定であることを示し、ユーザーエクスペリエンスが低下する可能性があります。 -
onAudioUnderrun
は、オーディオのアンダーランが発生したときに呼び出されます。 アンダーランは音に聞こえる不具合を引き起こし、ドロップされたビデオフレームよりも目立ちます。
AnalyticsListener
は addAnalyticsListener
で player
に追加することが可能です。 audio リスナーおよび video リスナーにも対応するメソッドがあります。
あなたのアプリとユーザーにとって、どのイベントが重要であるかを考えてみてください。 詳細については、「プレーヤ イベントをリスニングする」を参照してください。 イベント リスナーについては以上です!
これまで、ExoPlayer の PlayerControlView
を使用して、ユーザーに再生コントローラーを表示してきました。
Screenshot: デフォルトの再生コントローラー
これらのコントロールの機能またはルック アンド フィールを変更したい場合はどうすればよいでしょうか。 幸運にも、これらのコントロールは高度にカスタマイズ可能です。
最初の簡単なカスタマイズは、コントローラーをまったく使用しないことです。 これは、activity_player.xml
内の PlayerView
要素で use_controller
属性を使用することにより簡単に行うことができます。
-
use_controller
をfalse
に設定すると、コントロールは表示されなくなります:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
- 以下の名前空間を
FrameLayout
に追加します:
activity_player.xml
<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">
これで試してください。
Customize the behaviour
PlayerControlView
にはその振る舞いに影響を与えるいくつかの属性があります。 コントローラの動作をカスタマイズするには、show_timeout
、fastforward_increment
、および rewind_increment
を使用します。
-
app:use_controller="false"
を削除します。 -
show_timeout
,fastforward_increment
およびrewind_increment
を使用するようにプレーヤー ビューを変更します:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="10000" app:fastforward_increment="30000" app:rewind_increment="30000"/>
-
show_timeout
値は、ユーザーが最後に操作した後にコントロールが非表示になるまでの遅延をミリ秒単位でPlayerView
に通知します。 -
fastforward_increment
とrewind_increment
の値は、ユーザーが早送りまたは巻き戻しボタンをタップしたときに、プレーヤーが前方または後方にジャンプする時間をミリ秒単位で伝えます。
PlayerControlView
の属性もプログラムで設定できます。
外見のカスタマイズ
まあ、これは良いスタートです。 しかし、PlayerControlView
の見た目を変えたい場合や、どのボタンを表示するかを変更したい場合はどうすればよいでしょうか。 PlayerControlView
の実装では、ボタンが存在することを前提としていないので、ボタンを削除したり、新しいボタンを追加するのは簡単です。
PlayerControlView
をカスタマイズする方法を見てみましょう。
- フォルダ
player-lib/res/layout/
. - レイアウト フォルダのコンテキスト メニューから、新規作成 – レイアウト リソース ファイルを選択して
custom_player_control_view.xml
.
に新しいレイアウト ファイル custom_player_control_view.xml
を作成します。
スクリーン ショット。
- ここから元のレイアウト ファイルを
custom_player_control_view.xml
にコピーします。 - ID
@id/exo_prev
と@id/exo_next
を持つImageButton
要素を削除してください。
カスタム レイアウトを使用するには、activity_player.xml
ファイルの PlayerView
要素の app:controller_layout_id
属性を設定する必要があります。
- 次のコード スニペットのように、カスタム ファイルのレイアウト ID を使用します。
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" app:controller_layout_id="@layout/custom_player_control_view"/>
- もう一度アプリを起動する。 プレーヤー コントロール ビューには、[前へ] および [次へ] ボタンがなくなりました。 前または次のボタンがないカスタム プレーヤー コントロール ビュー
Layout ファイルで好きな変更を適用することができます。 デフォルトでは、Android テーマの色が選択されます。 アプリのデザインに合わせて、これを上書きできます。
-
ImageButton
要素にandroid:tint
属性を追加する:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
- カスタム ファイル内で見つけたすべての
android:textColor
属性を同じ色に変更します:#FF00A6FF
.
custom_player_control_view.xml
<TextView android:id="@id/exo_position" android:textColor="#FF00A6FF"/><TextView android:id="@id/exo_duration" android:textColor="#FF00A6FF"/>
- アプリケーションを実行します。 これで、美しい色の UI コンポーネントができました!
Screenshot: 着色されたボタンとテキスト ビュー
デフォルト スタイルをオーバーライドする
カスタム レイアウト ファイルを作成し、
activity_player.xml
でcontroller_layout_id
を使用してそれを参照しましたね。PlayerControlView
のソース・コードを見ると、レイアウトにR.layout.exo_player_control_view
を使っていることがわかります。- 追加した
controller_layout_id
属性を削除します。 - ファイル
custom_player_control_view.xml
を削除します。
activity_player.xml
のPlayerView
は現在次のようになっています:activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
- ライブラリモジュール
player-lib
のres/layout
フォルダにexo_player_control_view.xml
というファイルを作成します。 - 次のコードを
exo_player_control_view.xml
に挿入して、再生ボタン、一時停止ボタン、ロゴ付きのImageView
を追加します。xml**<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layoutDirection="ltr" android:background="#CC000000" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingTop="4dp" android:orientation="horizontal"> <ImageButton android:id="@id/exo_play" style="@style/ExoMediaButton.Play"/> <ImageButton android:id="@id/exo_pause" style="@style/ExoMediaButton.Pause"/> </LinearLayout> <ImageView android:contentDescription="@string/logo" android:src="@drawable/google_logo" android:layout_width="match_parent" android:layout_height="wrap_content"/></LinearLayout>
ここで、独自の要素を追加して、標準のコントロール要素と混ぜることができる方法を示しています。
ExoPlayerView
では、カスタム コントロールを使用し、コントロールとの対話時に表示と非表示を切り替えるすべてのロジックが保持されます。 ExoPlayer をアプリに統合することについて多くを学びました。Learn more
-