ÿÿ フローイベントã®å‡¦ç† - Android | Adapty ドキュメント

フローã¨ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã®ã‚¤ãƒ™ãƒ³ãƒˆå‡¦ç† - Android

ã“ã®ã‚¬ã‚¤ãƒ‰ã§ã¯ã€è³¼å…¥ãƒ»å¾©å…ƒãƒ»ãƒ—ãƒ­ãƒ€ã‚¯ãƒˆé¸æŠžãƒ»ãƒ•ãƒ­ãƒ¼è¡¨ç¤ºã«é–¢ã™ã‚‹ã‚¤ãƒ™ãƒ³ãƒˆå‡¦ç†ã«ã¤ã„ã¦èª¬æ˜Žã—ã¾ã™ã€‚ボタンã®å‡¦ç†ï¼ˆãƒ•ローを閉ã˜ã‚‹ã€ãƒªãƒ³ã‚¯ã‚’é–‹ããªã©ï¼‰ã‚‚別途実装ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚詳ã—ãã¯ãƒœã‚¿ãƒ³ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã®å‡¦ç†ã«é–¢ã™ã‚‹ã‚¬ã‚¤ãƒ‰ã‚’ã”覧ãã ã•ã„。

Flow Builderã‚„Paywall Builderã§è¨­å®šã—ãŸãƒ•ローやペイウォールã¯ã€è³¼å…¥ã‚„復元ã®ãŸã‚ã®è¿½åŠ ã‚³ãƒ¼ãƒ‰ã¯ä¸è¦ã§ã™ã€‚ãŸã ã—ã€ã‚¢ãƒ—リãŒå¿œç­”ã§ãるイベントãŒç™ºç”Ÿã—ã¾ã™ã€‚ã“れらã®ã‚¤ãƒ™ãƒ³ãƒˆã«ã¯ã€ãƒœã‚¿ãƒ³æŠ¼ä¸‹ï¼ˆé–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã€URLã€ãƒ—ãƒ­ãƒ€ã‚¯ãƒˆé¸æŠžãªã©ï¼‰ã‚„購入関連アクションã®é€šçŸ¥ãŒå«ã¾ã‚Œã¾ã™ã€‚ã“れらã®ã‚¤ãƒ™ãƒ³ãƒˆã¸ã®å¿œç­”方法ã«ã¤ã„ã¦ã¯ã€ä»¥ä¸‹ã‚’ã”覧ãã ã•ã„。

Adapty SDK ãŒãƒ¢ãƒã‚¤ãƒ«ã‚¢ãƒ—リã«ã©ã®ã‚ˆã†ã«çµ±åˆã•れã¦ã„ã‚‹ã‹ã€å®Ÿéš›ã®ä¾‹ã‚’見ã¦ã¿ã¾ã›ã‚“ã‹ï¼Ÿãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã®è¡¨ç¤ºã€è³¼å…¥å‡¦ç†ã€ãã®ä»–ã®åŸºæœ¬æ©Ÿèƒ½ã‚’å«ã‚€å®Œå…¨ãªã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—を実演ã—ã¦ã„るサンプルアプリをã”覧ãã ã•ã„。

購入画é¢ã§è¡Œã‚れるプロセスを制御・監視ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆã¯ã€AdaptyFlowEventListener ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’実装ã—ã¦ãã ã•ã„。 デフォルトã®å‹•作をãã®ã¾ã¾ä½¿ã„ãŸã„å ´åˆã¯ã€AdaptyFlowDefaultEventListener を継承ã—ã¦ã€å¤‰æ›´ã—ãŸã„メソッドã®ã¿ã‚’オーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã§ãã¾ã™ã€‚

以下㯠AdaptyFlowDefaultEventListener ã®ãƒ‡ãƒ•ォルト動作ã§ã™ã€‚

ユーザー生æˆã‚¤ãƒ™ãƒ³ãƒˆ

プロダクトã®é¸æŠž

プロダクトãŒï¼ˆãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚·ã‚¹ãƒ†ãƒ ã«ã‚ˆã£ã¦ï¼‰è³¼å…¥ã®ãŸã‚ã«é¸æŠžã•れるã¨ã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

購入開始

ユーザーãŒè³¼å…¥ãƒ—ロセスを開始ã™ã‚‹ã¨ã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯Observerモードã§ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“。詳細㯠Android - Observerモードã§ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’Present ã™ã‚‹ ã‚’å‚ç…§ã—ã¦ãã ã•ã„。

購入æˆåŠŸã€ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã€ã¾ãŸã¯ä¿ç•™ä¸­

è³¼å…¥ãŒæˆåŠŸã™ã‚‹ã¨ã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
イベント例(クリックã—ã¦å±•開)
// Successful purchase
{
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// Cancelled purchase
{
  "purchaseResult": {
    "type": "UserCanceled"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// Pending purchase
{
  "purchaseResult": {
    "type": "Pending"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

ã“ã®ã‚±ãƒ¼ã‚¹ã§ã¯ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã‚’é–‰ã˜ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ã‚ªãƒ–ザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“。詳細㯠Android - オブザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’表示ã™ã‚‹ ã‚’ã”å‚ç…§ãã ã•ã„。

購入失敗

購入ãŒã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šå¤±æ•—ã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ã€‚Google Play Billing ã®ã‚¨ãƒ©ãƒ¼ï¼ˆæ”¯æ‰•ã„制é™ã€ç„¡åйãªãƒ—ロダクトã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯éšœå®³ï¼‰ã€ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³æ¤œè¨¼ã®å¤±æ•—ã€ãŠã‚ˆã³ã‚·ã‚¹ãƒ†ãƒ ã‚¨ãƒ©ãƒ¼ãŒå¯¾è±¡ã§ã™ã€‚ãªãŠã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã‚‹ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«çµæžœã‚’伴ㆠonPurchaseFinished をトリガーã—ã€ä¿ç•™ä¸­ã®æ”¯æ‰•ã„ã¯ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’トリガーã—ã¾ã›ã‚“。

public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
イベント例(クリックã—ã¦å±•開)
{
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ã‚ªãƒ–ザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“。詳細ã«ã¤ã„ã¦ã¯ã€Android - オブザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’表示ã™ã‚‹ãƒˆãƒ”ックをå‚ç…§ã—ã¦ãã ã•ã„。

ウェブ決済ナビゲーションã®å®Œäº†

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ã€ç‰¹å®šã®ãƒ—ロダクトã®ã‚¦ã‚§ãƒ–ペイウォールを開ã“ã†ã¨ã—ãŸå¾Œã«å‘¼ã³å‡ºã•れã¾ã™ã€‚ãƒŠãƒ“ã‚²ãƒ¼ã‚·ãƒ§ãƒ³ã®æˆåŠŸãƒ»å¤±æ•—ã«ã‹ã‹ã‚らãšå‘¼ã³å‡ºã•れã¾ã™ã€‚

public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}

パラメーター:

パラメーター説明
productウェブペイウォールãŒé–‹ã‹ã‚ŒãŸ AdaptyPaywallProduct。null ã®å ´åˆãŒã‚りã¾ã™ã€‚
errorウェブペイウォールã®ãƒŠãƒ“ゲーションã«å¤±æ•—ã—ãŸå ´åˆã¯ AdaptyError ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã€æˆåŠŸã—ãŸå ´åˆã¯ null。
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
// Successful navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": null
}

// Failed navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "web_navigation_failed",
    "message": "Failed to open web paywall",
    "details": {
      "underlyingError": "Browser unavailable"
    }
  }
}

購入ã®å¾©å…ƒæˆåŠŸ

購入ã®å¾©å…ƒãŒæˆåŠŸã™ã‚‹ã¨ã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "profile": {
    "accessLevels": {
      "premium": {
        "id": "premium",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    },
    "subscriptions": [
      {
        "vendorProductId": "premium_monthly",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    ]
  }
}

ユーザーãŒå¿…è¦ãª accessLevel ã‚’æŒã£ã¦ã„ã‚‹å ´åˆã¯ã€ç”»é¢ã‚’é–‰ã˜ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚ç¢ºèªæ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–スクリプションã®çŠ¶æ…‹ ã‚’å‚ç…§ã—ã¦ãã ã•ã„。

復元ã®å¤±æ•—

Adapty.restorePurchases() ãŒå¤±æ•—ã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

サブスクリプションã®ã‚¢ãƒƒãƒ—グレード

ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ—¢å­˜ã®ã‚µãƒ–スクリプションãŒã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªçŠ¶æ…‹ã§æ–°ã—ã„サブスクリプションを購入ã—よã†ã¨ã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’オーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ã¦æ–°ã—ã„購入ã®å‡¦ç†æ–¹æ³•を制御ã§ãã¾ã™ã€‚次ã®2ã¤ã®ã‚ªãƒ—ションãŒã‚りã¾ã™ï¼š

  1. ç¾åœ¨ã®ã‚µãƒ–スクリプションを新ã—ã„ã‚‚ã®ã«ç½®ãæ›ãˆã‚‹:
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(
        AdaptyPurchaseParameters.Builder()
            .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...))
            .build()
    )
    return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}
  1. 両方ã®ã‚µãƒ–スクリプションを維æŒã™ã‚‹ï¼ˆæ–°ã—ã„ã‚‚ã®ã‚’別途追加ã™ã‚‹ï¼‰ï¼š
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty)
    return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’オーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ãªã„å ´åˆã€ãƒ‡ãƒ•ォルトã®å‹•作ã§ã¯ä¸¡æ–¹ã®ã‚µãƒ–スクリプションãŒã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªçŠ¶æ…‹ã‚’ç¶­æŒã—ã¾ã™ï¼ˆAdaptyPurchaseParameters.Emptyを使用ã—ãŸå ´åˆã¨åŒã˜å‹•作ã§ã™ï¼‰ã€‚

å¿…è¦ã«å¿œã˜ã¦ã€è¿½åŠ ã®è³¼å…¥ãƒ‘ラメーターを設定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ï¼š

AdaptyPurchaseParameters.Builder()
    .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // optional - for replacing current subscription
    .withOfferPersonalized(true) // optional - if using personalized pricing
    .build()
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "product": {
    "vendorProductId": "premium_yearly",
    "localizedTitle": "Premium Yearly",
    "localizedDescription": "Premium subscription for 1 year",
    "localizedPrice": "$99.99",
    "price": 99.99,
    "currencyCode": "USD"
  },
  "subscriptionUpdateParams": {
    "replacementMode": "with_time_proration"
  }
}

データå–å¾—ã¨ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°

プロダクト読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼

åˆæœŸåŒ–時ã«ãƒ—ロダクトを渡ã•ãªã„å ´åˆã€AdaptyUI ã¯å¿…è¦ãªã‚ªãƒ–ジェクトをサーãƒãƒ¼ã‹ã‚‰è‡ªå‹•çš„ã«å–å¾—ã—ã¾ã™ã€‚ã“ã®æ“作ãŒå¤±æ•—ã—ãŸå ´åˆã€AdaptyUI ã¯æ¬¡ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’呼ã³å‡ºã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’報告ã—ã¾ã™ã€‚

public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

true ã‚’è¿”ã™ã¨ã€AdaptyUI 㯠2 秒後ã«ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å†è©¦è¡Œã—ã¾ã™ã€‚

レンダリングエラー

インターフェースã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸå ´åˆã€æ¬¡ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’呼ã³å‡ºã—ã¦å ±å‘Šã•れã¾ã™ï¼š

public override fun onError(
    error: AdaptyError,
    context: Context,
) {}
イベント例(クリックã—ã¦å±•開)
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render flow interface",
    "details": {
      "underlyingError": "Invalid flow configuration"
    }
  }
}

通常ã€ã“ã®ã‚ˆã†ãªã‚¨ãƒ©ãƒ¼ã¯ç™ºç”Ÿã—ãªã„ã¯ãšã§ã™ã€‚ã‚‚ã—é­é‡ã—ãŸå ´åˆã¯ã€ãœã²ã”連絡ãã ã•ã„。

ã‚·ã‚¹ãƒ†ãƒ ã®æˆ»ã‚‹ãƒœã‚¿ãƒ³

デフォルトã§ã¯ã€ãƒ•ローã¯ã‚·ã‚¹ãƒ†ãƒ ã®æˆ»ã‚‹ãƒœã‚¿ãƒ³ã‚„ãƒãƒƒã‚¯ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã§ã¯é–‰ã˜ã‚‰ã‚Œã¾ã›ã‚“。ユーザーã¯ã€ãƒ“ルダーã§è¨­å®šã—㟠Close ボタンや on_device_back アクションãªã©ã€ã‚ãªãŸãŒå®šç¾©ã—ãŸãƒ‘スを通ã˜ã¦ãƒ•ローを離れã¾ã™ã€‚ã‚·ã‚¹ãƒ†ãƒ ã®æˆ»ã‚‹ãƒœã‚¿ãƒ³ã§ãƒ•ローを閉ã˜ã‚‰ã‚Œã‚‹ã‚ˆã†ã«ã—ãŸã„å ´åˆã¯ã€onBackPressed をオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—㦠false ã‚’è¿”ã—ã€ãƒ›ã‚¹ãƒˆã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティã¾ãŸã¯ãƒ•ラグメントãŒãã®æŠ¼ä¸‹ã‚’å‡¦ç†ã§ãるよã†ã«ã—ã¦ãã ã•ã„:

public override fun onBackPressed(context: Context): Boolean {
    return false // let the host handle the back press (e.g. finish the activity or pop the fragment)
}

ã“ã®ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã¯ã€ç¾åœ¨ã®ç”»é¢ã« on_device_back アクションãŒè¨­å®šã•れã¦ã„ãªã„å ´åˆã«ã®ã¿å‘¼ã³å‡ºã•れã¾ã™ã€‚アクションãŒè¨­å®šã•れã¦ã„ã‚‹å ´åˆã¯ã€ãã¡ã‚‰ãŒå„ªå…ˆã•れã¦å†…部ã§å‡¦ç†ã•れã¾ã™ã€‚true ã‚’è¿”ã™ã¨ãã®ãƒ—レスを消費ã—(デフォルトã®å‹•作)ã€false ã‚’è¿”ã™ã¨ãƒ›ã‚¹ãƒˆå´ã®æˆ»ã‚‹å‡¦ç†ãŒå®Ÿè¡Œã•れã¾ã™ã€‚

予約済ã¿ã‚¤ãƒ™ãƒ³ãƒˆ

AdaptyFlowEventListener ã«ã¯ã€ãƒ•ローãŒã¾ã ä½¿ç”¨ã—ã¦ã„ãªã„機能å‘ã‘ã«ã„ãã¤ã‹ã®ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ãŒå®£è¨€ã•れã¦ã„ã¾ã™ã€‚ã“れらを実装ã™ã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“。AdaptyFlowDefaultEventListener ãŒã™ã§ã«no-opã®ãƒ‡ãƒ•ォルト実装をæä¾›ã—ã¦ã„ã¾ã™ã€‚

メソッド説明
onAnalyticEventフローã‹ã‚‰ã®ã‚«ã‚¹ã‚¿ãƒ åˆ†æžã‚¤ãƒ™ãƒ³ãƒˆç”¨ã«äºˆç´„ã•れã¦ã„ã¾ã™ã€‚フローã¯ã¾ã ã“れらをコードã«é€ä¿¡ã—ãªã„ãŸã‚ã€å®Ÿè£…ã¯ä¸è¦ã§ã™ã€‚
onShowAppRateフローã‹ã‚‰ã®ã‚¢ãƒ—リレビューリクエスト用ã«äºˆç´„ã•れã¦ã„ã¾ã™ã€‚フローã¯ã¾ã ã‚¢ãƒ—リレビューリクエストをトリガーã—ãªã„ãŸã‚ã€å®Ÿè£…ã¯ä¸è¦ã§ã™ã€‚
onShowRequestPermissionフローã‹ã‚‰ã®ã‚·ã‚¹ãƒ†ãƒ æ¨©é™ãƒªã‚¯ã‚¨ã‚¹ãƒˆï¼ˆãƒ—ッシュ通知やカメラアクセスãªã©ï¼‰ç”¨ã«äºˆç´„ã•れã¦ã„ã¾ã™ã€‚フローã¯ã¾ã æ¨©é™ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’トリガーã—ãªã„ãŸã‚ã€å®Ÿè£…ã¯ä¸è¦ã§ã™ã€‚

ã“ã®ã‚¬ã‚¤ãƒ‰ã§ã¯ã€è³¼å…¥ãƒ»å¾©å…ƒãƒ»ãƒ—ãƒ­ãƒ€ã‚¯ãƒˆé¸æŠžãƒ»ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã®ã‚¤ãƒ™ãƒ³ãƒˆå‡¦ç†ã«ã¤ã„ã¦èª¬æ˜Žã—ã¾ã™ã€‚ボタンæ“作(ペイウォールを閉ã˜ã‚‹ã€ãƒªãƒ³ã‚¯ã‚’é–‹ããªã©ï¼‰ã®å‡¦ç†ã‚‚実装ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚詳細ã¯ãƒœã‚¿ãƒ³ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã®å‡¦ç†ã«é–¢ã™ã‚‹ã‚¬ã‚¤ãƒ‰ã‚’å‚ç…§ã—ã¦ãã ã•ã„。

ペイウォールビルダーã§è¨­å®šã—ãŸãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã¯ã€è³¼å…¥ã‚„復元ã®ãŸã‚ã«è¿½åŠ ã®ã‚³ãƒ¼ãƒ‰ã‚’書ãå¿…è¦ã¯ã‚りã¾ã›ã‚“。ãŸã ã—ã€ã‚¢ãƒ—リãŒå¯¾å¿œã§ãるイベントをã„ãã¤ã‹ç”Ÿæˆã—ã¾ã™ã€‚ã“れらã®ã‚¤ãƒ™ãƒ³ãƒˆã«ã¯ã€ãƒœã‚¿ãƒ³æ“作(閉ã˜ã‚‹ãƒœã‚¿ãƒ³ã€URLã€ãƒ—ãƒ­ãƒ€ã‚¯ãƒˆé¸æŠžãªã©ï¼‰ã‚„ã€ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ä¸Šã§è¡Œã‚れãŸè³¼å…¥é–¢é€£ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã®é€šçŸ¥ãŒå«ã¾ã‚Œã¾ã™ã€‚ã“れらã®ã‚¤ãƒ™ãƒ³ãƒˆã¸ã®å¯¾å¿œæ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ä»¥ä¸‹ã‚’ã”覧ãã ã•ã„。

ã“ã®ã‚¬ã‚¤ãƒ‰ã¯ã€Adapty SDK v3.0以é™ãŒå¿…è¦ãªæ–°ã—ã„ペイウォールビルダーã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«å°‚用ã§ã™ã€‚

Adapty SDK ãŒãƒ¢ãƒã‚¤ãƒ«ã‚¢ãƒ—リã«ã©ã®ã‚ˆã†ã«çµ±åˆã•れã¦ã„ã‚‹ã‹ã€å®Ÿéš›ã®ä¾‹ã‚’見ã¦ã¿ã¾ã›ã‚“ã‹ï¼Ÿãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã®è¡¨ç¤ºã€è³¼å…¥å‡¦ç†ã€ãã®ä»–ã®åŸºæœ¬æ©Ÿèƒ½ã‚’å«ã‚€å®Œå…¨ãªã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—を実演ã—ã¦ã„るサンプルアプリをã”覧ãã ã•ã„。

購入画é¢ã§ç™ºç”Ÿã™ã‚‹ãƒ—ロセスを制御・監視ã—ãŸã„å ´åˆã¯ã€AdaptyUiEventListener ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’実装ã—ã¦ãã ã•ã„。

一部ã®ã‚±ãƒ¼ã‚¹ã§ãƒ‡ãƒ•ォルトã®å‹•作をãã®ã¾ã¾ä½¿ã„ãŸã„å ´åˆã¯ã€AdaptyUiDefaultEventListener を継承ã—ã€å¤‰æ›´ã—ãŸã„メソッドã ã‘をオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã§ãã¾ã™ã€‚

以下㯠AdaptyUiDefaultEventListener ã®ãƒ‡ãƒ•ォルト実装ã§ã™ã€‚

ユーザーãŒç”Ÿæˆã™ã‚‹ã‚¤ãƒ™ãƒ³ãƒˆ

プロダクトã®é¸æŠž

ユーザーã¾ãŸã¯ã‚·ã‚¹ãƒ†ãƒ ã«ã‚ˆã£ã¦ãƒ—ロダクトãŒè³¼å…¥ã®ãŸã‚ã«é¸æŠžã•れるã¨ã€æ¬¡ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

購入ã®é–‹å§‹

ユーザーãŒè³¼å…¥ãƒ—ロセスを開始ã™ã‚‹ã¨ã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ã‚ªãƒ–ザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“。詳細㯠Android - オブザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’表示ã™ã‚‹ ã‚’å‚ç…§ã—ã¦ãã ã•ã„。

è³¼å…¥ã®æˆåŠŸãƒ»ã‚­ãƒ£ãƒ³ã‚»ãƒ«ãƒ»ä¿ç•™

è³¼å…¥ãŒæˆåŠŸã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
// Successful purchase
{
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// Cancelled purchase
{
  "purchaseResult": {
    "type": "UserCanceled"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// Pending purchase
{
  "purchaseResult": {
    "type": "Pending"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

ãã®å ´åˆã¯ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã‚’é–‰ã˜ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯Observerモードã§ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“。詳細ã¯Android - Observerモードã§ã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーペイウォールをPresentトピックをå‚ç…§ã—ã¦ãã ã•ã„。

購入失敗

購入ãŒã‚¨ãƒ©ãƒ¼ã«ã‚ˆã‚Šå¤±æ•—ã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ã€‚ã“れã«ã¯ã€Google Play Billing ã®ã‚¨ãƒ©ãƒ¼ï¼ˆæ”¯æ‰•ã„制é™ã€ç„¡åйãªãƒ—ロダクトã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯éšœå®³ï¼‰ã€ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³æ¤œè¨¼ã®å¤±æ•—ã€ãŠã‚ˆã³ã‚·ã‚¹ãƒ†ãƒ ã‚¨ãƒ©ãƒ¼ãŒå«ã¾ã‚Œã¾ã™ã€‚ãªãŠã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã—ãŸå ´åˆã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«çµæžœã¨ã¨ã‚‚ã« onPurchaseFinished ãŒãƒˆãƒªã‚¬ãƒ¼ã•れã€ä¿ç•™ä¸­ã®æ”¯æ‰•ã„ã¯ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’トリガーã—ã¾ã›ã‚“。

public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
イベント例(クリックã—ã¦å±•開)
{
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ã‚ªãƒ–ザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“。詳細ã«ã¤ã„ã¦ã¯ã€Android - オブザーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ãƒ“ルダーã®ãƒšã‚¤ã‚¦ã‚©ãƒ¼ãƒ«ã‚’表示ã™ã‚‹ã‚’å‚ç…§ã—ã¦ãã ã•ã„。

ウェブ決済ナビゲーションã®å®Œäº†

ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ã€ç‰¹å®šã®ãƒ—ロダクトã®ã‚¦ã‚§ãƒ–ペイウォールを開ã“ã†ã¨ã—ãŸå¾Œã«å‘¼ã³å‡ºã•れã¾ã™ã€‚ãƒŠãƒ“ã‚²ãƒ¼ã‚·ãƒ§ãƒ³ã®æˆåŠŸãƒ»å¤±æ•—ã«é–¢ã‚らãšå‘¼ã³å‡ºã•れã¾ã™ã€‚

public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}

パラメーター:

パラメーター説明
productウェブペイウォールãŒé–‹ã‹ã‚ŒãŸ AdaptyPaywallProduct。null ã®å ´åˆãŒã‚りã¾ã™ã€‚
errorウェブペイウォールã®ãƒŠãƒ“ゲーションã«å¤±æ•—ã—ãŸå ´åˆã¯ AdaptyError ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã€æˆåŠŸã—ãŸå ´åˆã¯ null。
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
// Successful navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": null
}

// Failed navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "web_navigation_failed",
    "message": "Failed to open web paywall",
    "details": {
      "underlyingError": "Browser unavailable"
    }
  }
}

購入ã®ãƒªã‚¹ãƒˆã‚¢æˆåŠŸ

購入ã®ãƒªã‚¹ãƒˆã‚¢ãŒæˆåŠŸã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™ï¼š

public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "profile": {
    "accessLevels": {
      "premium": {
        "id": "premium",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    },
    "subscriptions": [
      {
        "vendorProductId": "premium_monthly",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    ]
  }
}

ユーザーãŒå¿…è¦ãª accessLevel ã‚’æŒã£ã¦ã„ã‚‹å ´åˆã¯ã€ç”»é¢ã‚’é–‰ã˜ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚ç¢ºèªæ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–スクリプションã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ ã‚’ã”覧ãã ã•ã„。

復元ã®å¤±æ•—

Adapty.restorePurchases() ãŒå¤±æ•—ã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¾ã™:

public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

サブスクリプションã®ã‚¢ãƒƒãƒ—グレード

イベント例(クリックã—ã¦å±•開)
{
  "product": {
    "vendorProductId": "premium_yearly",
    "localizedTitle": "Premium Yearly",
    "localizedDescription": "Premium subscription for 1 year",
    "localizedPrice": "$99.99",
    "price": 99.99,
    "currencyCode": "USD"
  },
  "subscriptionUpdateParams": {
    "replacementMode": "with_time_proration"
  }
}

データã®å–å¾—ã¨ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°

プロダクト読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼

åˆæœŸåŒ–時ã«ãƒ—ロダクトを渡ã•ãªã„å ´åˆã€AdaptyUI ã¯å¿…è¦ãªã‚ªãƒ–ジェクトをサーãƒãƒ¼ã‹ã‚‰è‡ªå‹•çš„ã«å–å¾—ã—ã¾ã™ã€‚ã“ã®æ“作ãŒå¤±æ•—ã—ãŸå ´åˆã€AdaptyUI ã¯ä»¥ä¸‹ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’呼ã³å‡ºã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’報告ã—ã¾ã™ï¼š

public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
イベント例(クリックã—ã¦å±•開)
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

true ã‚’è¿”ã™ã¨ã€AdaptyUI 㯠2 秒後ã«ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å†è©¦è¡Œã—ã¾ã™ã€‚

レンダリングエラー

インターフェースã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸå ´åˆã€ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒå‘¼ã³å‡ºã•れã¦ã‚¨ãƒ©ãƒ¼ãŒé€šçŸ¥ã•れã¾ã™ï¼š

public override fun onRenderingError(
    error: AdaptyError,
    context: Context,
) {}
イベントã®ä¾‹ï¼ˆã‚¯ãƒªãƒƒã‚¯ã—ã¦å±•開)
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}

通常ã€ã“ã®ã‚ˆã†ãªã‚¨ãƒ©ãƒ¼ã¯ç™ºç”Ÿã—ãªã„ã¯ãšã§ã™ã€‚ã‚‚ã—é­é‡ã—ãŸå ´åˆã¯ã€ãœã²ã”連絡ãã ã•ã„。

ÿÿÿÿ