SDK ランタイムでは、広告 SDK をサンドボックス環境で実行できるため、パブリッシャーのビュー階層にアクセスできません。広告を表示するために、プラットフォームが SandboxedSdkProvider.getView
API を SDK に公開して広告ビューを取得し、これを SurfacePackage
としてパッケージ化して IPC(プロセス間通信)経由でクライアント アプリケーションに送信します。これにはいくつかの欠点があります。これについては以下で説明します。このドキュメントでは、こうした課題に対処するために開発中の、Jetpack ライブラリ案も紹介します。
プラットフォーム API を拡張する理由
フレームワーク API は柔軟性を考慮して設計されており、UI 表示の間のサイドチャネルの構築のタスクをアプリと SDK に任せることができます。このサイドチャネルは次の処理を行います。
- SDK が全期間にわたって複数の広告ビューを管理し、SDK によって作成された広告 UI がどうなるかを把握できるようにします。
- ビューの作成とコンテンツ バインディングを分離します。サイドチャネルを使用すると、SDK は広告リクエストに対応するオブジェクトをアプリ(コンテンツ)に返すことができます。これは、アプリが適切と判断した場合はいつでも、広告コンテナにバインドできます。
- プロセス全体で UI を表示するために使用される、基盤となるプラットフォーム構造を取り除きます(プラットフォームは現在、
SurfaceControlViewhost
を使用して、そこからSurfacePackage
を生成します)。 - 広告コンテナの UI が変更されたときに、SDK ランタイムの広告 SDK が自動的に通知を受け取れるようにします。パブリッシャーが広告コンテナのレイアウトを変更しても、パブリッシャーが明示的に API を呼び出して通知しない限り、SDK はその変更を認識しません。
- ユーザーに表示されるジャンクを発生させることなく、広告 UI と広告コンテナのサイズ変更を同期します。
- 下位互換性を自動的に管理します。
SurfacePackage
は、API レベル 30 より前のバージョンでは使用できません。また、SDK ランタイムがなく、SDK がパブリッシャーに対してプロセスローカルであるデバイスでは、ビューを直接 SDK から取得できる場合に広告用のSurfacePackage
を作成することは無駄になります。サイドチャネルは、この複雑さを SDK およびアプリ デベロッパー コードから取り除きます。 - 広告 UI がコンポーザブルとシームレスに統合されます。ビューを使用しない Jetpack Compose デベロッパーは、引き続きビューを使用している SDK デベロッパーが生成した UI を引き続きホストできます。
UI ライブラリ
UI ライブラリは、上記で詳説した複雑さを取り除き、パブリッシャーと SDK がプロセス全体で UI を表示するために使用できるサイドチャネルを提供します。また、ユーザーによる UI およびデバイスの操作に応じて、UI を最新の状態に維持します。
UI ライブラリは 3 つ(コア、クライアント、プロバイダ)あります。コアライブラリは、クライアント ライブラリとプロバイダ ライブラリで使用されるインターフェースを提供します。UI プロバイダ(通常は SDK)はプロバイダ ライブラリに依存し、UI のコンシューマ(通常はパブリッシャー)はクライアント ライブラリに依存します。クライアント ライブラリとプロバイダ ライブラリが連携して、UI セッションの作成と維持に必要なサイドチャネルを形成します。
API
SDK ランタイム UI 表示用の API は次のとおりです。
SandboxedUiAdapter
: SDK で作成され、パブリッシャーの UI に表示するコンテンツを取得する方法を提供します。
SandboxedSdkView
: パブリッシャーにより作成されます。SandboxedUiAdapter
を通じて取得したコンテンツを保持するコンテナです。
Session
: SandboxedUiAdapter.openSession()
に応じて SDK によって作成されます。1 つの UI セッション呼び出しを表します。これにより、SDK とパブリッシャー間の通信トンネルの SDK 側が形成されます。また、SandboxedSdkView
の変更(ウィンドウのデタッチ、サイズ変更、設定の変更など)に関する通知を受け取ります。
SessionClient
: クライアント ライブラリで作成され、SDK とパブリッシャー間の通信トンネルのパブリッシャー側を形成します。
SandboxedSdkUiSessionStateChangedListener
: パブリッシャーによって作成されます。SandboxedSdkView
に関連付けられた UI セッションの状態の変更のリスナー。
これらの API について詳しくは、privacysandbox-ui リファレンス ドキュメントをご覧ください。
制御フロー
次の図は、さまざまなシナリオでのクライアント UI ライブラリとプロバイダ UI ライブラリ間のやり取りを示しています。
上の図は、パブリッシャーがプログラムまたは XML を使用して SandboxedSdkView
を作成し、SDK 定義の API を介して SDK から取得した SdkSandboxUiAdapter
にアタッチする方法を示しています。すべての UI 状態の変化を監視するには、パブリッシャーは SdkSandboxUiAdapter
をアタッチする前に SandboxedSdkUiSessionStateChangedListener
を SandboxedSdkView
に追加する必要があります。
この図は、パブリッシャーのアクティビティが構成の変更を処理するかどうかを示しています。
クライアント ライブラリが構成の変更を SDK に転送すると、
それに応じて UI を更新できますたとえば、ユーザーがデバイスを回転させた場合で、パブリッシャーが android:configChanges=["orientation"]
を設定してアクティビティで構成変更の処理を宣言している場合に、このフローがトリガーされる可能性があります。
この図は、SDK が広告コンテナの変更をリクエストする方法を
SessionClient
のメソッド。この API は、SDK が広告のサイズ変更をリクエストし、パブリッシャーが新しいサイズに合わせて広告コンテナのサイズを変更する必要があるときにトリガーされます。これは、mraid.resize()
などのユーザー操作に応じて発生することがあります。
この図は、SandboxedSdkView
がウィンドウからデタッチされたときにセッションがどのように終了するかを示しています。セッションは、SDK で SessionClient.onSessionError()
を呼び出すことで、任意の時点で(たとえば、ユーザーがネットワーク接続を失ったときなどに)閉じることもできます。
Z オーダー
クライアント UI ライブラリは、内部で SurfaceView
を使用して SDK の UI をホストします。SurfaceView
は Z オーダーを使用して、パブリッシャーのウィンドウの上または下に UI を表示できます。これは、ブール値 setOnTop
を受け取る SandboxedSdkView.orderProviderUiAboveClientUi()
メソッドによって制御されます。
setOnTop
が true
の場合、SandboxedSdkView
のすべての android.view.MotionEvent
が SDK に送信されます。false
の場合、これらはパブリッシャーに送信されます。デフォルトでは、モーション イベントは SDK に送信されます。
通常、パブリッシャーは広告ビューのデフォルトの Z オーダーを変更する必要がありません。ただし、広告を覆う UI(プルダウン メニューなど)を表示する場合は、Z オーダーを一時的にデフォルトから切り替えて、覆う UI 要素が閉じたらこれを復元するようにする必要があります。現在、クライアント UI ライブラリでこのプロセスを自動化する方法を検討しています。
スクロール
広告 UI がパブリッシャー ウィンドウの上の Z に配置されると、広告 UI からの MotionEvents
が SDK に送信されます。広告 UI で開始されるスクロール操作とフリング操作は特別な処理が行われます。
- 垂直スクロールとフリングのジェスチャーは、パブリッシャーのコンテナに送信され、コンテナによって処理されます。広告 UI が配置されるパブリッシャーのコンテナが垂直方向にスクロールできる場合に、これは優れた UX を実現できます。SDK やパブリッシャー側で特別な作業を行う必要はありません。
- 水平方向のスクロール操作とフリング操作は、SDK に送信され、SDK によって処理されます。広告 UI 自体が水平方向にスクロールできる場合(広告カルーセルなど)に、これは優れた UX を実現できます。
実装ガイド
SDK は以下を実装する必要があります。
SandboxedUiAdapter
: SDK 定義の API(loadAd
など)に応答してパブリッシャーに返されます。この実装のopenSession()
メソッドを使用して、SDK のサーバーに広告リクエストを行い、そのリクエストに対応する広告ビューを準備するために使用する必要があります。Session**
: これはSandboxedUiAdapter.openSession
の呼び出し。これにより ライブラリを取得して広告 UI を取得し、この API の変更を SDK に通知します。すべてSession
メソッドはここで実装する必要があります。
パブリッシャーは、次のことを行う必要があります。
- XML またはプログラムによって
SandboxedSdkView
を作成します。 SandboxedSdkUiSessionStateChangedListener
をSandboxedSdkView
にアタッチして、UI の変化を監視します。- SDK が提供する
SandboxedUiAdapter
をSandboxedSdkView
にアタッチします。 - 通常どおり
SandboxedSdkView
をウィンドウに追加し、SDK との UI セッションの作成とメンテナンスはクライアント ライブラリに任せます。 - 適宜、
SandboxedSdkUiSessionChangedListener
によってレポートされる状態の変化に対応します。たとえば、SDK がセッションを予期せず閉じた場合に、パブリッシャーはSandboxedSdkView
を静止画像に置き換えたり、ビュー階層から削除したりできます。 - プルダウン メニューなど、広告 UI を覆うような遷移を行う場合は、一時的に
orderProviderUiAboveClientUi
を false にして、パブリッシャーのウィンドウの下に広告 UI を配置します。プルダウン メニューが閉じたら、orderProviderUiAboveClientUi
を呼び出してtrue
にします。
プラットフォーム API の今後
UI ライブラリがベータ版になった時点で、UI の表示に関連する SDK ランタイム プラットフォーム API(SdkSandboxManager.requestSurfacePackage()
と SandbxedSdkProvider.getView()
)のサポートを終了する予定です。
自由回答形式の質問
- UI ライブラリが自動的に処理する必要がある、より一般的な広告 UI ユースケースはありますか?
- 広告 UI を表示するためにどの UI フレームワークを使用していますか?UI ライブラリをそれらのフレームワークと統合する際に、問題が発生することが予想されますか?
- スクロール可能なパブリッシャーのコンテナにスクロール可能な広告 UI を配置するのは一般的なユースケースですか?この場合の、広告 UI とコンテナのスクロールはいずれの方向ですか?ユーザーが広告 UI でスクロールを開始したときに想定される動作は何ですか?