ExoPlayerでメディアストリーミング

4ec261ee5a0bd0cc.png

Screenshot: YouTube Android アプリ

ExoPlayer は、Android の低レベル メディア API の上に構築されたアプリ レベルのメディア プレーヤーです。 ExoPlayer には、Android に組み込まれた MediaPlayer よりも多くの利点があります。 MediaPlayer と同じメディア フォーマットの多くに加え、DASH や SmoothStreaming などのアダプティブ フォーマットをサポートしています。 ExoPlayer は、高度なカスタマイズと拡張が可能で、多くの高度なユースケースに対応できます。

前提条件

  • 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 フォルダー (N00 から 04) にはこのコード ラボでの各ステップの望ましい最終状態が含まれます。 これらはスタンドアロンの Android Studio プロジェクトで、それぞれインポートすることができます。

初期プロジェクトのインポート

  1. Start Android Studio.
  2. Choose File > New > Import Project*.*
  3. Import the initial project from exoplayer-codelab-00.

f2e5feb9ade6c7f7.png

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 などの機能を利用することもできます。

  1. アプリの展開と実行ですべてがうまくいっていることを確認します。 アプリは黒い背景で画面を埋めるはずです。

21c0dae6245fbd31.png

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 モジュールの追加を参照してください。

  1. Open the player-lib module.
  2. 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

  1. Open the layout resource file activity_player.xml from the player-lib module.
  2. Place the cursor inside the FrameLayout element.
  3. 入力開始 <PlayerView and let Android Studio autocomplete the PlayerView element.Authorized.を追加します。
  4. widthheightにはmatch_parentを使用します。
  5. 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要素をビデオビューと呼びます。

  1. PlayerActivity では、ビデオ ビューを見つけて、アクティビティの onCreate メソッドで適切に設定する必要があります。

PlayerActivity.java

@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
  1. あなたの PlayerActivity クラスに playerView メンバー フィールドを追加してください。 ビューのタイプが PlayerView.

Note: Android Studio のクイックフィックス機能を使用すると、メンバーフィールドを自動的に追加することができます。 デフォルトの

View

b0f7f70115bb90e5.png

ではなく、

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 を使用して playerMediaItem を追加します。

  1. initializePlayer:

PlayerActivity.java

private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}

R.string.media_url_mp3strings.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 つのメソッドをオーバーライドする必要があります。

  1. PlayerActivity を開いた状態で、[コード] メニュー > [メソッドのオーバーライド]… をクリックします。
  2. 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 まで待ってからプレーヤーを初期化します。

  1. 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);}

hideSystemUionResume で呼ばれるヘルパーメソッドで、フルスクリーン体験ができるようにするためのメソッドです。

  1. onPauseonStopreleasePlayer(まもなく作成)でリソースを解放します。

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 で保存したステート情報をプレーヤに供給するだけです。

  1. initializePlayer に以下を追加します:

PlayerActivity.java

private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}

ここで、

  • setPlayWhenReady再生用のすべてのリソースが取得されると同時に再生を開始するかどうかをプレイヤーに指示します。 playWhenReady は最初は true なので、アプリを最初に実行したときに自動的に再生が始まります。
  • seekTo は、特定のウィンドウ内の特定の位置にシークすることをプレイヤーに指示します。 currentWindowplaybackPosition は両方ともゼロに初期化され、アプリを最初に実行したときに再生が最初から始まります。
  • prepare はプレーヤーに再生に必要なすべてのリソースを取得するように指示します。

Play audio

最後に、完了しました!

  • prepare は、再生するために必要なリソースをすべて取得するように指示しています。 アプリを起動して MP3 ファイルを再生し、埋め込まれたアートワークを確認します。

    1d049aead0483777.png

    スクリーンショット。

    Test the activity lifecycle

    Test the app works in all the different states of the activity lifecycle.

    1. Start another app and put your app in the foreground again.The app playing a single track.

      App Store では、アプリを起動し、埋め込まれたアートワークを見ることができます。 正しい位置で再開されますか。

    2. アプリを一時停止し、バックグラウンドに移動して、再びフォアグラウンドに移動します。 一時停止状態でバックグラウンドにしたとき、一時停止状態に固執しますか。
    3. アプリを回転させます。 縦から横へ、そしてまた横へと向きを変えた場合、どのように動作しますか?

    Play video

    動画を再生したい場合は、メディア項目の URI を MP4 ファイルに変更するだけで、簡単に再生できます。

    1. initializePlayer の URI を R.string.media_url_mp4 に変更します。
    2. アプリを再度起動し、ビデオ再生でバックグラウンド化した後の動作もテストします。

    PlayerActivity.java

    private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }

    PlayerView がすべてを行います。 アートワークの代わりに、ビデオはフルスクリーンでレンダリングされます。

    4ebd0b0f98593691.png

    Screenshot: ビデオを再生しているアプリ。

    You rock! ライフサイクル管理、保存された状態、および UI コントロールを完備した、Android でのフルスクリーン メディア ストリーミング用アプリを作成したのです!

    現在のアプリは単一のメディア ファイルを再生しますが、複数のメディア ファイルを次々に再生したい場合はどうしたらよいでしょうか。 そのためには、プレイリストが必要です。

    プレイリストは、addMediaItem を使用して player にさらに MediaItem を追加することによって作成することができます。 これにより、シームレスな再生が可能になり、バッファリングはバックグラウンドで処理されるため、ユーザーはメディア項目を変更する際にバッファリング スピナーを見ることはありません。

    1. initializePlayer に次のコードを追加します:

    PlayerActivity.java

    private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }

    プレーヤー コントロールがどう動作しているかを確認する。 1f79fee4d082870f.png39627002c03ce320.png を使用してメディア項目のシーケンスをナビゲートできます。

    7b5c034dafabe1bd.png

    Screenshot: Next および Previous ボタンを表示する再生コントロール

    これはかなり便利です! 詳細については、Media Items と Playlist の開発者向けドキュメント、および Playlist API に関するこの記事を参照してください。

    Adaptive ストリーミングは、利用可能なネットワーク帯域幅に基づいてストリームの品質を変化させることにより、メディアをストリーミングするための手法です。 これにより、ユーザーは帯域幅が許容する最高品質のメディアを体験できます。

    通常、同じメディア コンテンツは、異なる品質 (ビットレートと解像度) を持つ複数のトラックに分割されます。 プレーヤーは、使用可能なネットワーク帯域幅に基づいてトラックを選択します。

    各トラックは、通常 2 秒から 10 秒の間の所定の持続時間のチャンクに分割されます。 これにより、利用可能な帯域幅の変化に応じて、プレーヤーはトラックをすばやく切り替えることができます。

    Adaptive track selection

    Adaptive ストリーミングの中心は、現在の環境に最も適したトラックを選択することです。 アダプティブ トラック セレクションを使用して、アダプティブ ストリーミング メディアを再生するようにアプリを更新します。

    1. 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 タイプを指定しなければならないからです。

    1. 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);}
    1. アプリを再起動すると、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

    1. PlayerActivityPlaybackStateListener 型のプライベート メンバーを宣言します。
    2. Create a TAG constant, which you use for logging later.

    PlayerActivity.Listener を使用して、プレーヤーがどの状態にあるかをログに記録します。java

    private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
    1. onCreate の先頭にある playbackStateListener をインスタンス化します(まだコンパイルできませんが、すぐに修正します)。

    PlayerActivity.java

    @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
    1. 内部クラス PlaybackStateListener を自動的に作成するにはクイックフィックスを使います。

    b59ce69a22595ba7.png

    Screenshot: 不足しているクラスを作成するためのクイック修正メニュー

    1. Player.EventListener インターフェイスを実装します。 これは、エラーや再生状態の変更など、重要なプレーヤーのイベントを通知するために使用されます。
    2. 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つになることができます:

    十分なデータがバッファされていないため、現在の位置から再生できない。

    現在の位置からすぐに再生できるようになった。 これは、プレーヤのplayWhenReadyプロパティがtrueの場合、プレーヤが自動的にメディア再生を開始することを意味する。 false の場合、プレーヤーは一時停止します。

    State

    Description

    ExoPlayer.STATE_IDLE

    プレーヤーが初期状態になりましたがまだ準備されていない状態です。

    ExoPlayer.STATE_BUFFERING

    ExoPlayer.STATE_READY

    ExoPlayer.STATE_ENDED

    プレーヤーがメディアの再生を完了しました。

    Register your listener

    コールバックが呼ばれるために、playbackStateListenerをプレーヤーに登録する必要があります。 initializePlayer.

    1. 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.プレーヤーからの参照で、メモリーリークを起こさないようにします。

    1. releasePlayer:

    PlayerActivity.java

    private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
    1. logcat を開いてアプリを実行。
    2. UI コントロールを使って再生を模索、一時停止、再開してください。 ログに再生状態の変化が見られるはずです。

    さらに深く

    ExoPlayer は、ユーザーの再生体験を理解するのに役立つ、他の多くのリスナーを提供します。 オーディオとビデオ用のリスナー、およびすべてのリスナーからのコールバックを含む AnalyticsListener があります。 最も重要なメソッドは次のとおりです。

    • onRenderedFirstFrame は、ビデオの最初のフレームがレンダリングされるときに呼び出されます。 これを使用して、ユーザーが画面上に意味のあるコンテンツを表示するために待たなければならなかった時間を計算することができます。
    • onDroppedVideoFrames は、ビデオ フレームがドロップされたときに呼び出されます。 ドロップされたフレームは、再生が不安定であることを示し、ユーザーエクスペリエンスが低下する可能性があります。
    • onAudioUnderrun は、オーディオのアンダーランが発生したときに呼び出されます。 アンダーランは音に聞こえる不具合を引き起こし、ドロップされたビデオフレームよりも目立ちます。

    AnalyticsListeneraddAnalyticsListenerplayer に追加することが可能です。 audio リスナーおよび video リスナーにも対応するメソッドがあります。

    あなたのアプリとユーザーにとって、どのイベントが重要であるかを考えてみてください。 詳細については、「プレーヤ イベントをリスニングする」を参照してください。 イベント リスナーについては以上です!

    これまで、ExoPlayer の PlayerControlView を使用して、ユーザーに再生コントローラーを表示してきました。

    bcfe17eebcad9e13.png

    Screenshot: デフォルトの再生コントローラー

    これらのコントロールの機能またはルック アンド フィールを変更したい場合はどうすればよいでしょうか。 幸運にも、これらのコントロールは高度にカスタマイズ可能です。

    最初の簡単なカスタマイズは、コントローラーをまったく使用しないことです。 これは、activity_player.xml 内の PlayerView 要素で use_controller 属性を使用することにより簡単に行うことができます。

    1. use_controllerfalse に設定すると、コントロールは表示されなくなります:

    activity_player.xml

    <com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
    1. 以下の名前空間を FrameLayout に追加します:

    activity_player.xml

    <FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">

    これで試してください。

    Customize the behaviour

    PlayerControlView にはその振る舞いに影響を与えるいくつかの属性があります。 コントローラの動作をカスタマイズするには、show_timeoutfastforward_increment、および rewind_increment を使用します。

    1. app:use_controller="false" を削除します。
    2. 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_incrementrewind_increment の値は、ユーザーが早送りまたは巻き戻しボタンをタップしたときに、プレーヤーが前方または後方にジャンプする時間をミリ秒単位で伝えます。

    PlayerControlView の属性もプログラムで設定できます。

    外見のカスタマイズ

    まあ、これは良いスタートです。 しかし、PlayerControlViewの見た目を変えたい場合や、どのボタンを表示するかを変更したい場合はどうすればよいでしょうか。 PlayerControlView の実装では、ボタンが存在することを前提としていないので、ボタンを削除したり、新しいボタンを追加するのは簡単です。

    PlayerControlView をカスタマイズする方法を見てみましょう。

    1. フォルダ player-lib/res/layout/.
    2. に新しいレイアウト ファイル custom_player_control_view.xml を作成します。

    3. レイアウト フォルダのコンテキスト メニューから、新規作成 – レイアウト リソース ファイルを選択して custom_player_control_view.xml.

    ae1e3795726d4e4e.png

    スクリーン ショット。

    1. ここから元のレイアウト ファイルを custom_player_control_view.xml にコピーします。
    2. ID @id/exo_prev@id/exo_next を持つ ImageButton 要素を削除してください。

    カスタム レイアウトを使用するには、activity_player.xml ファイルの PlayerView 要素の app:controller_layout_id 属性を設定する必要があります。

    1. 次のコード スニペットのように、カスタム ファイルのレイアウト 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"/>
    1. もう一度アプリを起動する。 プレーヤー コントロール ビューには、[前へ] および [次へ] ボタンがなくなりました。 前または次のボタンがないカスタム プレーヤー コントロール ビュー

      Layout ファイルで好きな変更を適用することができます。 デフォルトでは、Android テーマの色が選択されます。 アプリのデザインに合わせて、これを上書きできます。

      1. ImageButton 要素に android:tint 属性を追加する:

      custom_player_control_view.xml

      <ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
      1. カスタム ファイル内で見つけたすべての 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"/>
      1. アプリケーションを実行します。 これで、美しい色の UI コンポーネントができました!

      e9835d65d6dd0634.png

      Screenshot: 着色されたボタンとテキスト ビュー

      デフォルト スタイルをオーバーライドする

      カスタム レイアウト ファイルを作成し、activity_player.xmlcontroller_layout_id を使用してそれを参照しましたね。 PlayerControlView のソース・コードを見ると、レイアウトに R.layout.exo_player_control_view を使っていることがわかります。

      1. 追加した controller_layout_id 属性を削除します。
      2. ファイル custom_player_control_view.xml を削除します。

      activity_player.xmlPlayerView は現在次のようになっています:

      activity_player.xml

      <com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
      1. ライブラリモジュール player-libres/layout フォルダに exo_player_control_view.xml というファイルを作成します。
      2. 次のコードを 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

    コメントを残す

    メールアドレスが公開されることはありません。