ExoPlayer は、Android 用のアプリレベルのメディア プレーヤーです。このガイドでは、IMA Android DAI SDK をラップする ExoPlayer IMA 拡張機能を使用して、広告とコンテンツの両方を含むメディア ストリームをリクエストして再生する方法について説明します。
この拡張機能には次のようなメリットがあります。
- IMA と機能を統合するために必要なコードが簡素化されます。
- 新しいバージョンの IMA へのアップデートに必要な開発時間を短縮できます。
ExoPlayer IMA 拡張機能は、HLS と DASH ストリーミング プロトコルをサポートしています。概要は次のとおりです。
ExoPlayer-IMA 拡張機能のストリームのサポート | ||
---|---|---|
ライブ配信 | VOD ストリーム | |
HLS | ||
DASH |
DASH ライブ ストリームは ExoPlayer-IMA バージョン 1.1.0 以降でサポートされています。
このガイドは ExoPlayer ガイドに基づいており、完全なアプリを作成して拡張機能を統合する方法について説明します。完全なサンプルアプリの例については、GitHub の ExoPlayerExample
をご覧ください。
前提条件
- Android Studio
- AndroidX Media3 ExoPlayer バージョン 1.0.0 以降(DAI サポートのため)。
新しい Android Studio プロジェクトの作成
Android Studio プロジェクトを作成する手順は次のとおりです。
- Android Studio を起動します。
- [Start a new Android Studio project] を選択します。
- [プロジェクトの選択] ページで、[No Activity] テンプレートを選択します。
- [次へ] をクリックします。
[Configure your project] ページでプロジェクトに名前を付け、言語として Java を選択します。
[完了] をクリックします。
ExoPlayer IMA 拡張機能をプロジェクトに追加する
拡張機能のインポートをアプリレベルの build.gradle ファイルの dependencies
セクションに追加します。
Multidex を使用するようにアプリを構成し、有効にします。これは、拡張機能のサイズのために必要であり、minSdkVersion
が Android 4.4W(API レベル 20)以下に設定されているアプリでは必須です。
次の例をご覧ください。
app/build.gradle
android { ... defaultConfig { applicationId "com.google.ads.interactivemedia.v3.samples.videoplayerapp" minSdkVersion 19 targetSdkVersion 34 multiDexEnabled true versionCode 1 versionName "1.0" } ... } dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.media3:media3-ui:1.1.1' implementation 'androidx.media3:media3-exoplayer:1.1.1' implementation 'androidx.media3:media3-exoplayer-hls:1.1.1' implementation 'androidx.media3:media3-exoplayer-dash:1.1.1' // Adding the ExoPlayer IMA extension for ads will also include the IMA // SDK as a dependency. implementation 'androidx.media3:media3-exoplayer-ima:1.1.1' }
IMA SDK で広告のリクエストに必要なユーザー権限を追加します。
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name"> <!-- Required permissions for the IMA SDK --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ... </manifest>
インテント宣言を追加する
Android 11(API レベル 30)以降をターゲットとするアプリの場合、IMA SDK の現行バージョンおよび最新バージョンでは、ウェブリンクを開くためにインテントを明示的に宣言する必要があります。広告のクリックスルー([詳細] ボタンをクリックするユーザー)を有効にするには、次のスニペットをアプリのマニフェスト ファイルに追加します。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name"> ... </application> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="https" /> </intent> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http" /> </intent> </queries> </manifest>
ExoPlayer の UI を設定する
ExoPlayer が使用する PlayerView
オブジェクトを作成します。
androidx.constraintlayout.widget.ConstraintLayout
を LinearLayout
に変更します。これは ExoPlayer IMA 拡張機能に推奨されています。
次の例をご覧ください。
app/src/main/res/layout/activity_my.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:background="@android:color/black" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MyActivity" tools:ignore="MergeRootFrame"> <androidx.media3.ui.PlayerView android:id="@+id/player_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
ストリーム パラメータを追加する
プロジェクトをテストするためのストリーム アセットのサンプルについては、IMA ストリームのサンプルページをご覧ください。独自のストリームの設定については、DAI に関するアド マネージャーのセクションをご覧ください。
このステップではライブ ストリームの設定について説明しますが、ExoPlayer IMA 拡張機能は DAI VOD ストリームもサポートしています。アプリが VOD ストリームを処理するために必要な変更については、ビデオ オンデマンド(VOD)ストリームの手順をご覧ください。
ExoPlayer IMA 拡張機能をインポートする
ExoPlayer 拡張機能のインポート ステートメントを追加します。
次のプライベート変数を MyActivity.java
に追加します。
PlayerView
ExoPlayer
ImaServerSideAdInsertionMediaSource.AdsLoader
ImaServerSideAdInsertionMediaSource.AdsLoader.State
Big Buck Bunny (Live) HLS ストリームのアセットキーを追加して、このストリームでテストします。他にも、IMA のサンプル ストリーム ページでテストできるストリームをご覧いただけます。
AdsLoader
の状態の保存と取得を行う KEY_ADS_LOADER_STATE
定数を作成します。
次の例をご覧ください。
app/src/main/java/com/example/project name/MyActivity.java
import static androidx.media3.common.C.CONTENT_TYPE_HLS; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.annotation.OptIn; import androidx.media3.common.MediaItem; import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource; import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionUriBuilder; import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import androidx.media3.exoplayer.util.EventLogger; import androidx.media3.ui.PlayerView; import androidx.multidex.MultiDex; ... public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private PlayerView playerView; private ExoPlayer player; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; }
adsLoader
インスタンスを作成する
onCreate
メソッドを上書きして PlayerView
を検出し、保存されている AdsLoader.State
を確認します。これは、adsLoader
オブジェクトの開始時に使用できます。
また、アプリのメソッド数と minSdkVersion
で必要な場合は、Multidex を有効にします(ステップ 2 を参照)。
次の例をご覧ください。
app/src/main/java/com/example/project name/MyActivity.java
... public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private PlayerView playerView; private ExoPlayer player; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); MultiDex.install(this); playerView = findViewById(R.id.player_view); // Checks if there is a saved AdsLoader state to be used later when // initiating the AdsLoader. if (savedInstanceState != null) { Bundle adsLoaderStateBundle = savedInstanceState.getBundle(KEY_ADS_LOADER_STATE); if (adsLoaderStateBundle != null) { adsLoaderState = ImaServerSideAdInsertionMediaSource.AdsLoader.State.CREATOR.fromBundle( adsLoaderStateBundle); } } } }
プレーヤーを初期化するメソッドを追加する
プレーヤーを初期化するメソッドを追加して、次の操作を行います。
AdsLoader
インスタンスを作成します。ExoPlayer
を作成します。- ライブ ストリームのアセットキーで
MediaItem
を作成します。 MediaItem
をプレーヤーに設定します。
次の例をご覧ください。
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { ... // Create a server side ad insertion (SSAI) AdsLoader. private ImaServerSideAdInsertionMediaSource.AdsLoader createAdsLoader() { ImaServerSideAdInsertionMediaSource.AdsLoader.Builder adsLoaderBuilder = new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(this, playerView); // Attempt to set the AdsLoader state if available from a previous session. if (adsLoaderState != null) { adsLoaderBuilder.setAdsLoaderState(adsLoaderState); } return adsLoaderBuilder.build(); } private void initializePlayer() { adsLoader = createAdsLoader(); // Set up the factory for media sources, passing the ads loader. DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(this); DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(dataSourceFactory); // MediaSource.Factory to create the ad sources for the current player. ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory = new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, mediaSourceFactory); // 'mediaSourceFactory' is an ExoPlayer component for the DefaultMediaSourceFactory. // 'adsMediaSourceFactory' is an ExoPlayer component for a MediaSource factory for IMA server // side inserted ad streams. mediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory); // Create an ExoPlayer and set it as the player for content and ads. player = new ExoPlayer.Builder(this).setMediaSourceFactory(mediaSourceFactory).build(); playerView.setPlayer(player); adsLoader.setPlayer(player); // Build an IMA SSAI media item to prepare the player with. Uri ssaiLiveUri = new ImaServerSideAdInsertionUriBuilder() .setAssetKey(SAMPLE_ASSET_KEY) .setFormat(CONTENT_TYPE_HLS) // Use CONTENT_TYPE_DASH for dash streams. .build(); // Create the MediaItem to play, specifying the stream URI. MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiLiveUri); // Prepare the content and ad to be played with the ExoPlayer. player.setMediaItem(ssaiMediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); } }
プレーヤーを解放するメソッドを追加する
プレーヤーを解放するメソッドを、次のシーケンスで追加します。
- プレーヤー参照を null に設定し、プレーヤーのリソースを解放します。
adsLoader
の状態を解放します。
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { ... private void releasePlayer() { // Set the player references to null and release the player's resources. playerView.setPlayer(null); player.release(); player = null; // Release the adsLoader state so that it can be initiated again. adsLoaderState = adsLoader.release(); }
プレーヤー イベントを処理する
最後に、アクティビティのライフサイクル イベントのコールバックを作成して、ストリームの再生を処理します。
Android SDK バージョン 24 以降をサポートするには:
バージョン 24 より前の Android SDK をサポートするには:
- onResume()
- onPause()
onStart()
と onResume()
は playerView.onResume()
にマッピングされ、onStop()
と onPause()
は playerView.onPause()
にマッピングされます。
このステップでは、onSaveInstanceState()
イベントを使用して adsLoaderState
の保存も試行します。
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { ... @Override public void onStart() { super.onStart(); if (Util.SDK_INT > 23) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onResume() { super.onResume(); if (Util.SDK_INT <= 23 || player == null) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onPause() { super.onPause(); if (Util.SDK_INT <= 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onStop() { super.onStop(); if (Util.SDK_INT > 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onSaveInstanceState(Bundle outState) { // Attempts to save the AdsLoader state to handle app backgrounding. if (adsLoaderState != null) { outState.putBundle(KEY_ADS_LOADER_STATE, adsLoaderState.toBundle()); } } ... }
VOD ストリームの設定(省略可)
アプリで広告付きの VOD コンテンツを再生する必要がある場合は、次のことを行う必要があります。
- VOD テスト ストリーム用に
CMS ID
とVideo ID
を追加します。 ImaServerSideAdInsertionUriBuilder()
を使用して SSAI VOD URI を作成します。- この新しい URI をプレーヤーのメディア アイテムとして使用します。
app/src/main/java/com/example/project name/MyActivity.java
public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private static final String SAMPLE_CMS_ID = "2528370"; private static final String SAMPLE_VIDEO_ID = "tears-of-steel"; ... private void initializePlayer() { ... Uri ssaiVodUri = new ImaServerSideAdInsertionUriBuilder() .setContentSourceId(SAMPLE_CMS_ID) .setVideoId(SAMPLE_VIDEO_ID) .setFormat(CONTENT_TYPE_HLS) .build(); // Create the MediaItem to play, specifying the stream URI. MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiVodUri); // Prepare the content and ad to be played with the ExoPlayer. player.setMediaItem(ssaiMediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); }
これで、これで、ExoPlayer IMA 拡張機能を使用してメディア ストリームをリクエストして再生できるようになりました。完全なコードについては、GitHub の Android DAI サンプルをご覧ください。