Android SDKでのフローとペイウォールの取得を最適化する

Android でフローやペイウォールを確実に取得するには、3つのことを実現する必要があります:高速なレンダリング、オーディエンスターゲットのバリアントの返却、そしてネットワークが遅い場合のグレースフルなフォールバック。以下のルールでは、それを実現するためのタイミング、キャッシュ、フォールバックパターンを説明します。

Tip

これらのルールは、Adapty.activate() と Adapty.identify() がすでに完了していることを前提としています。Android SDKの呼び出し順序を参照してください。

ルールと注意点

これをやるこれはやらない理由
表示しようとしているプレースメントを取得するか、preloadFlows(SDK 4.1+)でキャッシュをウォームアップする。起動時に独自の並行 getFlow 呼び出しをばらまく。手製のプリフェッチバーストはメインスレッドをブロックし、黒い画面を引き起こす。preloadFlows はこのために設計されており、バッチを並行で実行する。
アトリビューションが解決される機会を得た後(例:activate の 1〜2 秒後、または setOnProfileUpdatedListener が発火した後)に getFlow を取得する。Application.onCreate() で getFlow を呼び出す。アトリビューションがまだ反映されていない。フローはデフォルトのオーディエンスに対して解決され、セグメントや ASA のパーソナライゼーションが暗黙的にスキップされる。
loadTimeout を設定し、すべてのプレースメントにフォールバックペイウォールを設定する。getFlow を無制限に待ち続ける。タイムアウトがないと、接続状況が悪いユーザーはネットワークが解決するまで白紙画面を見続けるか、アプリを閉じてしまう。

fetchPolicy と loadTimeout パラメーターのリファレンスはペイウォールとプロダクトの取得を、適切なプレースメントの選び方はプレースメントを参照してください。

プレースメントのプリロード

Info

preloadFlows と preloadFlowsForDefaultAudience は SDK バージョン 4.1 以降で利用できます。

preloadFlows はフローの JSON を事前にキャッシュします(プレースメントごとに 1 リクエスト)。その後は通常通り使用できます。フローには getFlow、ビュー設定には getFlowConfiguration を使います。

fetchPolicy は後続の getFlow がどのレイヤーを最初に読み込むかを決定するもので、キャッシュへのアクセス可否を制御するものではありません。

  • ReturnCacheDataElseLoad はまずプリロード済みのコピーを読み込み、キャッシュに何もない場合のみネットワークにアクセスします。ReturnCacheDataIfNotExpiredElseLoad(maxAgeMillis) は、コピーが maxAgeMillis より新しい間は同様の動作をします。
  • デフォルトの ReloadRevalidatingCacheData はまずネットワークにアクセスし、リクエストが失敗またはタイムアウトした場合にプリロード済みのコピーにフォールバックします。

プリロードはどちらの場合も効果がありますが、動作は異なります。キャッシュファーストポリシーではリクエスト自体がなくなり、デフォルトではリクエストは維持されつつ、フォールバック用のウォームコピーが確保されます。

ボタンをまだタップしていない状態で、セッションで使用するプレースメントは分かっているが、まだ表示したくない場合に使用します — たとえば、activate と identify が解決した直後、まだタップされていないボタンの裏にあるフローなどです。

パラメーター:

  • placementIds (必須): プリロードするプレースメント。空白や重複した ID は無視されます。
  • loadTimeout (オプション): バッチ全体ではなく、バッチ内の各プレースメントに適用されるタイムアウト。デフォルトは 5 秒で、1 秒未満の値は 1 秒に切り上げられます。

知っておくべき動作:

  • コールバックはすべてのプレースメントの試行が完了した後にのみ発火し、プレースメントごとの失敗をまとめて報告します。あるプレースメントが失敗しても、他のプレースメントの処理は停止しません。
  • プレースメントがタイムアウト、サーバーエラー、またはネットワークエラーで失敗した場合、SDKはそのプレースメントのフォールバックバリアントにフォールバックします。その他の失敗はそのまま報告されます。
  • プリロードはキャッシュをウォームアップするだけです。コンテンツを返すわけではないため、表示するには引き続き getFlow を呼び出す必要があります。

プリロードがカバーする範囲

フローは複数のレイヤーを経て画面に表示されます。プリロードは getFlow と同様に、最初のレイヤーのみをカバーします。

レイヤー取得元プリロードによるウォーミング
フロー JSON — 選択されたバリアント、プロダクト ID、リモートコンフィグgetFlowあり
UI レイアウト — 画面の構造、スタイル、テキストgetFlowConfigurationなし
画像(動画要素の代わりに表示される静止フレームを含む)getFlowConfiguration(バックグラウンド処理)なし
動画ファイル画面レンダリング時のシステムプレイヤーSDK ではキャッシュされない

getFlowConfiguration はレイアウトが返ってくるまで待機するため、プリロード後でも特定のレイアウトへの最初のリクエストにはラウンドトリップのコストがかかります。その後、SDK はそのレイアウトを独自のディスクキャッシュに保持します。このキャッシュはアプリの再起動をまたいで維持され、ネットワーク呼び出しより先に読み込まれるため、コストは毎回ではなく最初のリクエスト時のみに発生します。レイアウトを取得した後、SDK はその呼び出しとは独立して画像のキャッシュを開始します。画面の表示をブロックすることはなく、完了を通知するコールバックやエラーも存在しません。

どのプレースメントが失敗したかを確認する

コールバックは、コード REQUEST_FAILED (2005) を持つ AdaptyPreloadPlacementsError をバッチ全体に対して受け取ります。個別の失敗を確認するには、プレースメント ID をキーとするマップである preloadErrors プロパティを参照してください。

Adapty.preloadFlows(listOf("onboarding", "main_paywall")) { error ->
    if (error is AdaptyPreloadPlacementsError) {
        error.preloadErrors.forEach { (placementId, placementError) ->
            // log or retry the individual placement
        }
    }
}

preloadErrors は AdaptyPreloadPlacementsError にのみ存在するため、まず型を確認してください — それ以外の AdaptyError は、プレースメントごとの失敗とは別の原因によるものです。

オーディエンスセグメンテーションをスキップする

オーディエンスセグメンテーションを待たずにキャッシュをウォームアップするには、デフォルトオーディエンスのバリアントを使用します。loadTimeout は不要です:

Adapty.preloadFlowsForDefaultAudience(listOf("main_paywall")) { error -> }

アプリバンドルからファーストスクリーンのメディアを表示する

フローは画像や動画を Adapty からダウンロードします。ファーストスクリーンのメディアを即座に表示するには、アプリバンドルからメディアを提供してください。これは、既存のネイティブオンボーディングのビジュアルなど、すでにアプリに含まれているメディアを再利用する際に便利な方法です。

  1. フロービルダーまたはペイウォールビルダーで、画像または動画にカスタムメディアIDを設定します。そこでアップロードしたファイルはフォールバックとして使用されます。
  2. アプリの res/raw または assets フォルダにファイルを追加します。
  3. getFlowView でフロービューを作成する際、customAssets にそのIDに対応するバンドル済みファイルを渡します。
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
val bundledAssets = AdaptyCustomAssets.of(
    "welcome_video" to
            AdaptyCustomVideoAsset.file(
                FileLocation.fromResId(requireContext(), R.raw.welcome),
                preview = AdaptyCustomImageAsset.file(
                    FileLocation.fromResId(requireContext(), R.drawable.welcome_poster),
                ),
                resolution = AdaptyCustomVideoAsset.Resolution(width = 1080, height = 1920),
            ),
)

val flowView = AdaptyUI.getFlowView(
    activity,
    flowConfiguration,
    products,
    eventListener,
    insets,
    bundledAssets,
)

バンドルファイルはアプリのダウンロードサイズを増やすため、ユーザーが最初に目にするメディアのみをバンドルしてください。

バンドルしていないメディアもすぐに表示されます。ビューの設定には各画像(動画のスチルフレームを含む)の低解像度のコピーが含まれており、フルファイルが読み込まれるまでの間、その低解像度コピーが表示されます。

customAssets の詳細なリファレンスについては、アセットのカスタマイズを参照してください。

通信状態が悪い環境への対応

通信状態が常に悪い市場(農村部、交通機関内、ルーティングの問題が多い地域など)向けには以下を推奨します:

  • 初回以外のすべてのフェッチで fetchPolicy を AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad に設定する。
  • Adapty ダッシュボードで全プレースメントにフォールバックペイウォールを設定する。
  • loadTimeout を 3〜5 秒に設定し、タイムアウト発生時はフォールバックを受け入れる。
  • getProfile の完了をフロー表示の条件にしない。getFlow は独立して呼び出し、プロファイルの取得が遅くても UI をブロックしないようにする。