ÿÿ React Native ã§ãƒ•ローã¨ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’表示ã™ã‚‹ | Adapty ドキュメント

フローã¨ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã®è¡¨ç¤º - React Native

Display flows and paywalls
✦
フロー Flow Builder ã§ä½œæˆâ€”—デãƒã‚¤ã‚¹ä¸Šã§ãƒã‚¤ãƒ†ã‚£ãƒ–ã«ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã•れã€WebView ã¯ä¸è¦
✦
Paywall Builder ã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ« 既存ã®ã™ã¹ã¦ã® Paywall Builder コンテンツ

フローã¾ãŸã¯ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’フローービルダーã§ä½œæˆã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«è¡¨ç¤ºã™ã‚‹ãŸã‚ã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°å‡¦ç†ã‚’モãƒã‚¤ãƒ«ã‚¢ãƒ—リã®ã‚³ãƒ¼ãƒ‰ã«å®Ÿè£…ã™ã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“。ãã®ã‚ˆã†ãªãƒ•ローã«ã¯ã€è¡¨ç¤ºã™ã‚‹ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¨è¡¨ç¤ºæ–¹æ³•ã®ä¸¡æ–¹ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚

å§‹ã‚ã‚‹å‰ã«ã€ä»¥ä¸‹ã‚’確èªã—ã¦ãã ã•ã„:

  1. フローã¾ãŸã¯ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’作æˆã—ã¦ã„ã‚‹ã“ã¨ã€‚
  2. プレースメントã«è¿½åŠ ã—ã¦ã„ã‚‹ã“ã¨ã€‚
  3. フローをå–å¾—ã—ã¦ãƒ“ューを準備ã—ã¦ã„ã‚‹ã“ã¨ã€‚

ã“ã®ã‚¬ã‚¤ãƒ‰ã¯ãƒ•ローãŠã‚ˆã³ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーã§ä½œæˆã•れãŸãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«å°‚用ã§ã™ã€‚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 });

ペイウォールビルダーを使用ã—ã¦ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’カスタマイズã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«è¡¨ç¤ºã™ã‚‹ãŸã‚ã«ãƒ¢ãƒã‚¤ãƒ«ã‚¢ãƒ—リã®ã‚³ãƒ¼ãƒ‰ã§ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã™ã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“。ã“ã®ã‚ˆã†ãªãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã«ã¯ã€ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«å†…ã«è¡¨ç¤ºã™ã‚‹å†…容ã¨ãã®è¡¨ç¤ºæ–¹æ³•ã®ä¸¡æ–¹ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚

å§‹ã‚ã‚‹å‰ã«ã€ä»¥ä¸‹ã‚’確èªã—ã¦ãã ã•ã„:

  1. ペイウォールを作æˆã—ã¦ã„る。
  2. ペイウォールをプレースメントã«è¿½åŠ ã—ã¦ã„る。
  3. ペイウォールをフェッãƒã—ã¦ãƒ“ューを準備ã—ã¦ã„る。

ã“ã®ã‚¬ã‚¤ãƒ‰ã¯ã€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 ãŒã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãƒãƒ¼ã®å¾Œã‚ã¾ã§æ‹¡å¼µã•れã¦ã„ãªã„å ´åˆã§ã‚‚ã€ãã®ä¸Šéƒ¨ã«ãƒ“ジュアルオーãƒãƒ¼ãƒ¬ã‚¤ãŒè¡¨ç¤ºã•れるã“ã¨ãŒã‚りã¾ã™ã€‚ã“れを削除ã™ã‚‹ã«ã¯ã€ã‚¢ãƒ—ãƒªã«æ¬¡ã®ãƒ–ールリソースを追加ã—ã¦ãã ã•ã„:

  1. android/app/src/main/res/values ã«ç§»å‹•ã—ã¾ã™ã€‚bools.xml ファイルãŒãªã„å ´åˆã¯ä½œæˆã—ã¦ãã ã•ã„。

  2. 次ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’追加ã—ã¾ã™ï¼š

<resources>
    <bool name="adapty_paywall_enable_safe_area_paddings">false</bool>
</resources>

ã“ã®å¤‰æ›´ã¯ã‚¢ãƒ—リ内ã®ã™ã¹ã¦ã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã«ã‚°ãƒ­ãƒ¼ãƒãƒ«ã«é©ç”¨ã•れるã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。

ÿÿÿÿ