
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-04exoplayer-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-libmodule.
- Add the following lines to the dependenciessection 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.xmlfrom theplayer-libmodule.
- Place the cursor inside the FrameLayoutelement.
- 入力開始 <PlayerViewand let Android Studio autocomplete thePlayerViewelement.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 TAGconstant, 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 onPlaybackStateChangedby 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
 
-