フローとペイウォールの表示 - React Native
フローまたはペイウォールをフローービルダーで作成した場合、ユーザーに表示するためのレンダリング処理をモバイルアプリのコードに実装する必要はありません。そのようなフローには、表示するコンテンツと表示方法の両方が含まれています。
始める前に、以下を確認してください:
- フローまたはペイウォールを作成していること。
- プレースメントに追加していること。
- フローを取得してビューを準備していること。
このガイドはフローおよびペイウォールビルダーで作成されたペイウォール専用です。SDK v4.0以降が必要です。フローの表示方法はリモートコンフィグペイウォールとは異なります。
- リモートコンフィグペイウォールの表示については、リモートコンフィグで設計されたペイウォールのレンダリングを参照してください。
Adapty React Native SDK では、フローとペイウォールを表示する方法が2つあります:
-
Reactコンポーネント: アプリのアーキテクチャやナビゲーションシステムに組み込めるコンポーネントです。
-
モーダル表示
Reactコンポーネント
フローを既存のコンポーネントツリーに埋め込むには、React Nativeのコンポーネント階層にAdaptyFlowViewコンポーネントを直接使用します。埋め込みコンポーネントを使うことで、アプリのアーキテクチャやナビゲーションシステムに統合できます。
AdaptyFlowView コンポーネントは、レンダリング時(設定と画像の読み込み時)にビューを作成します。事前に読み込むには、アプリの早い段階で同じフローに対して createFlowView を呼び出してください。コンポーネントはキャッシュされたデータを再利用し、ダウンロードを待たずにレンダリングします。
function MyFlow({ flow }) {
const flowParams = useMemo(() => ({
loadTimeoutMs: 3000,
}), []);
const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>(() => {}, []);
const onProductSelected = useCallback<FlowEventHandlers['onProductSelected']>((productId) => {}, []);
const onPurchaseStarted = useCallback<FlowEventHandlers['onPurchaseStarted']>((product) => {}, []);
const onPurchaseCompleted = useCallback<FlowEventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []);
const onPurchaseFailed = useCallback<FlowEventHandlers['onPurchaseFailed']>((error, product) => {}, []);
const onRestoreStarted = useCallback<FlowEventHandlers['onRestoreStarted']>(() => {}, []);
const onRestoreCompleted = useCallback<FlowEventHandlers['onRestoreCompleted']>((profile) => {}, []);
const onRestoreFailed = useCallback<FlowEventHandlers['onRestoreFailed']>((error) => {}, []);
const onAppeared = useCallback<FlowEventHandlers['onAppeared']>(() => {}, []);
const onError = useCallback<FlowEventHandlers['onError']>((error) => {}, []);
const onLoadingProductsFailed = useCallback<FlowEventHandlers['onLoadingProductsFailed']>((error) => {}, []);
const onUrlPress = useCallback<FlowEventHandlers['onUrlPress']>((url) => {}, []);
const onCustomAction = useCallback<FlowEventHandlers['onCustomAction']>((actionId) => {}, []);
const onWebPaymentNavigationFinished = useCallback<FlowEventHandlers['onWebPaymentNavigationFinished']>(() => {}, []);
return (
<AdaptyFlowView
flow={flow}
params={flowParams}
style={styles.flow}
onCloseButtonPress={onCloseButtonPress}
onProductSelected={onProductSelected}
onPurchaseStarted={onPurchaseStarted}
onPurchaseCompleted={onPurchaseCompleted}
onPurchaseFailed={onPurchaseFailed}
onRestoreStarted={onRestoreStarted}
onRestoreCompleted={onRestoreCompleted}
onRestoreFailed={onRestoreFailed}
onAppeared={onAppeared}
onError={onError}
onLoadingProductsFailed={onLoadingProductsFailed}
onCustomAction={onCustomAction}
onUrlPress={onUrlPress}
onWebPaymentNavigationFinished={onWebPaymentNavigationFinished}
/>
);
}モーダル表示
フローをスタンドアロン画面として表示するには、createFlowView メソッドで作成した view に対して view.present() メソッドを使用します。各 view は一度しか使用できません。再度フローを表示する必要がある場合は、createFlowView をもう一度呼び出して新しい view インスタンスを作成してください。
同じ view を再作成せずに再利用することは禁止されています。AdaptyUIError.viewAlreadyPresented エラーが発生します。
const view = await createFlowView(flow);
// Optional: handle flow events (close, purchase, restore, etc)
// view.setEventHandlers({ ... });
try {
await view.present();
} catch (error) {
// handle the error
}setEventHandlers を複数回呼び出すと、以前に設定したハンドラーが上書きされ、デフォルトおよび指定したイベントの既存ハンドラーがすべて置き換えられます。
iOSのプレゼンテーションスタイルを設定する
present() メソッドに iosPresentationStyle パラメータを渡すことで、iOS でのフローの表示方法を設定できます。このパラメータには 'full_screen'(デフォルト)または 'page_sheet' を指定できます。
try {
await view.present({ iosPresentationStyle: 'page_sheet' });
} catch (error) {
// handle the error
}開発者定義タイマーを使用する
モバイルアプリで開発者定義タイマーを使用するには、timerId(この例では CUSTOM_TIMER_NY)を使います。これは Adapty ダッシュボードで設定した開発者定義タイマーの Timer ID です。これにより、アプリはタイマーを正しい値(例:元日までの残り時間を現在時刻から引いた 13d 09h 03m 34s のような形式)で動的に更新できます。
この例では、CUSTOM_TIMER_NY は Adapty ダッシュボードで設定した開発者定義タイマーの Timer ID です。timerResolver により、アプリはタイマーに正しい値(例:タイマーの終了時刻(元旦など)から現在時刻を引いた 13d 09h 03m 34s)を動的に反映できます。
ダイアログを表示する
Android でフロービューが表示されている場合は、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では、通常の RN アラートがフロービューの背面に表示されるため、ユーザーには見えません。このメソッドを使用すると、すべてのプラットフォームでフローの前面に正しくダイアログが表示されます。
try {
const action = await view.showDialog({
title: 'Close paywall?',
content: 'You will lose access to exclusive offers.',
primaryActionTitle: 'Stay',
secondaryActionTitle: 'Close',
});
if (action === 'secondary') {
// User confirmed - close the flow
await view.dismiss();
}
// If primary - do nothing, user stays
} catch (error) {
// handle error
}サブスクリプションを別のものに切り替える
Androidで、ユーザーが既存のサブスクリプションをアクティブな状態で新しいサブスクリプションを購入しようとした場合、フロービューの作成時にサブスクリプション更新パラメーターを渡すことで、新しい購入の処理方法を制御できます。現在のサブスクリプションを新しいものに切り替えるには、createFlowViewのproductPurchaseParamsにoldSubVendorProductIdとprorationModeパラメーターを指定してください。
const productPurchaseParams = flow.paywalls
.flatMap((variation) => variation.productIdentifiers)
.map((productId) => {
let params = {};
if (Platform.OS === 'android') {
params.android = {
subscriptionUpdateParams: {
oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION',
prorationMode: 'with_time_proration',
},
};
}
return { productId, params };
});
const view = await createFlowView(flow, { productPurchaseParams });ペイウォールビルダーを使用してペイウォールをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングする必要はありません。このようなペイウォールには、ペイウォール内に表示する内容とその表示方法の両方が含まれています。
始める前に、以下を確認してください:
- ペイウォールを作成している。
- ペイウォールをプレースメントに追加している。
- ペイウォールをフェッチしてビューを準備している。
このガイドは、SDK v3.0 以降が必要な新しいペイウォールビルダーのペイウォール専用です。ペイウォールの表示方法は、ペイウォールビルダーのバージョンやリモートコンフィグのペイウォールによって異なります。
- リモートコンフィグのペイウォールを表示する方法については、リモートコンフィグで設計されたペイウォールのレンダリングを参照してください。
Adapty React Native SDK には、ペイウォールを表示する方法が 2 つあります:
-
React コンポーネント: アプリのアーキテクチャやナビゲーションシステムに組み込めるコンポーネントです。
-
モーダル表示
Reactコンポーネント
Reactコンポーネントアプローチを使用するには、SDK 3.14.0以降が必要です。
既存のコンポーネントツリー内にペイウォールを埋め込むには、React Nativeのコンポーネント階層の中でAdaptyPaywallViewコンポーネントを直接使用します。埋め込みコンポーネントを使うことで、アプリのアーキテクチャやナビゲーションシステムに組み込むことができます。
Androidでは、ペイウォールがステータスバーの背後まで拡張されていない場合、ペイウォールの上部にビジュアルオーバーレイが表示されることがあります。ペイウォールではこれをオフにすることをお勧めします。ペイウォール上部のビジュアルオーバーレイ(Android)をご覧ください。
function MyPaywall({ paywall }) {
const paywallParams = useMemo(() => ({
loadTimeoutMs: 3000,
}), []);
const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []);
const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []);
const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []);
const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []);
const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []);
const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []);
const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []);
const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []);
const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []);
const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []);
const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []);
const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => {}, []);
const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []);
const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []);
return (
<AdaptyPaywallView
paywall={paywall}
params={paywallParams}
style={styles.paywall}
onCloseButtonPress={onCloseButtonPress}
onProductSelected={onProductSelected}
onPurchaseStarted={onPurchaseStarted}
onPurchaseCompleted={onPurchaseCompleted}
onPurchaseFailed={onPurchaseFailed}
onRestoreStarted={onRestoreStarted}
onRestoreCompleted={onRestoreCompleted}
onRestoreFailed={onRestoreFailed}
onPaywallShown={onPaywallShown}
onRenderingFailed={onRenderingFailed}
onLoadingProductsFailed={onLoadingProductsFailed}
onCustomAction={onCustomAction}
onUrlPress={onUrlPress}
onWebPaymentNavigationFinished={onWebPaymentNavigationFinished}
/>
);
}モーダル表示
ペイウォールをスタンドアロン画面として表示するには、createPaywallView メソッドで作成した view に対して view.present() メソッドを呼び出します。各 view は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、createPaywallView をもう一度呼び出して新しい view インスタンスを作成してください。
同じ view を再作成せずに再利用することは禁止されています。AdaptyUIError.viewAlreadyPresented エラーが発生します。
const view = await createPaywallView(paywall);
// Optional: handle paywall events (close, purchase, restore, etc)
// view.setEventHandlers({ ... });
try {
await view.present();
} catch (error) {
// handle the error
}setEventHandlers を複数回呼び出すと、指定したハンドラーで既存のハンドラーが上書きされます。デフォルトのハンドラーと以前に設定したハンドラーの両方が、対象のイベントについて置き換えられます。
iOS のプレゼンテーションスタイルを設定する
present() メソッドに iosPresentationStyle パラメーターを渡すことで、iOS でのペイウォールの表示方法を設定できます。このパラメーターには 'full_screen'(デフォルト)または 'page_sheet' を指定できます。
try {
await view.present({ iosPresentationStyle: 'page_sheet' });
} catch (error) {
// handle the error
}開発者定義タイマーを使用する
モバイルアプリで開発者定義タイマーを使用するには、timerId(この例では CUSTOM_TIMER_NY)を使います。これは Adapty ダッシュボードで設定した開発者定義タイマーの Timer ID です。これにより、アプリはタイマーを正しい値(例:13d 09h 03m 34s、タイマーの終了時刻(元日など)から現在時刻を引いた値)で動的に更新できます。
この例では、CUSTOM_TIMER_NY は Adapty ダッシュボードで設定した開発者定義タイマーの Timer ID です。timerResolver により、アプリはタイマーの終了時刻(元旦など)から現在時刻を引いた値として 13d 09h 03m 34s のような正確な値でタイマーを動的に更新します。
ダイアログを表示する
Android でペイウォールビューが表示されている場合、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では、通常の RN アラートがペイウォールビューの背後に表示されるため、ユーザーには見えません。このメソッドを使用することで、すべてのプラットフォームでペイウォールの前面にダイアログが正しく表示されます。
try {
const action = await view.showDialog({
title: 'Close paywall?',
content: 'You will lose access to exclusive offers.',
primaryActionTitle: 'Stay',
secondaryActionTitle: 'Close',
});
if (action === 'secondary') {
// User confirmed - close the paywall
await view.dismiss();
}
// If primary - do nothing, user stays
} catch (error) {
// handle error
}別のサブスクリプションへの切り替え
Androidで、ユーザーが既存のサブスクリプションを有効な状態で新しいサブスクリプションを購入しようとする場合、ペイウォールビューの作成時にサブスクリプション更新パラメータを渡すことで、新しい購入の処理方法を制御できます。現在のサブスクリプションを新しいサブスクリプションに切り替えるには、createPaywallView の productPurchaseParams に oldSubVendorProductId と prorationMode パラメータを指定してください。
const productPurchaseParams = paywall.productIdentifiers.map((productId) => {
let params = {};
if (Platform.OS === 'android') {
params.android = {
subscriptionUpdateParams: {
oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION',
prorationMode: 'with_time_proration',
},
};
}
return { productId, params };
});
const view = await createPaywallView(paywall, { productPurchaseParams });トラブルシューティング
ペイウォール上部のビジュアルオーバーレイ(Android)
この設定は React Native SDK 3.15.5 以降でサポートされており、ベア React Native プロジェクトでのみ利用できます。
Expo managed workflow を使用している場合、この Android リソースを直接追加することはできません。この設定を適用するには、対応する Android リソースを追加するカスタム Expo config プラグインを作成し、app.config.js に登録する必要があります。これは Expo がネイティブ Android プロジェクトを管理しているため必須です。
AdaptyPaywallView がステータスバーの後ろまで拡張されていない場合でも、その上部にビジュアルオーバーレイが表示されることがあります。これを削除するには、アプリに次のブールリソースを追加してください:
-
android/app/src/main/res/valuesに移動します。bools.xmlファイルがない場合は作成してください。 -
次のリソースを追加します:
<resources>
<bool name="adapty_paywall_enable_safe_area_paddings">false</bool>
</resources>この変更はアプリ内のすべてのペイウォールにグローバルに適用されることに注意してください。