---
title: "フローとペイウォールのイベント処理 - Android"
description: "Androidアプリでフローおよびペイウォールのイベントを処理する方法を説明します。"
---

:::important
このガイドでは、購入・復元・プロダクト選択・フロー表示に関するイベント処理について説明します。ボタンの処理（フローを閉じる、リンクを開くなど）も別途実装する必要があります。詳しくは[ボタンアクションの処理に関するガイド](android-handle-paywall-actions)をご覧ください。
:::
[Flow Builder](adapty-flow-builder)や[Paywall Builder](adapty-paywall-builder)で設定したフローやペイウォールは、購入や復元のための追加コードは不要です。ただし、アプリが応答できるイベントが発生します。これらのイベントには、ボタン押下（閉じるボタン、URL、プロダクト選択など）や購入関連アクションの通知が含まれます。これらのイベントへの応答方法については、以下をご覧ください。

:::tip

Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか？ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。

:::

購入画面で行われるプロセスを制御・監視する必要がある場合は、`AdaptyFlowEventListener` のメソッドを実装してください。
デフォルトの動作をそのまま使いたい場合は、`AdaptyFlowDefaultEventListener` を継承して、変更したいメソッドのみをオーバーライドできます。

以下は `AdaptyFlowDefaultEventListener` のデフォルト動作です。
### ユーザー生成イベント \{#user-generated-events\}

#### プロダクトの選択 \{#product-selection\}

プロダクトが（ユーザーまたはシステムによって）購入のために選択されると、このメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>

#### 購入開始 \{#started-purchase\}

ユーザーが購入プロセスを開始すると、このメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>

このメソッドはObserverモードでは呼び出されません。詳細は [Android - ObserverモードでペイウォールビルダーのペイウォールをPresent する](android-present-paywall-builder-paywalls-in-observer-mode) を参照してください。

#### 購入成功、キャンセル、または保留中 \{#successful-canceled-or-pending-purchase\}

購入が成功すると、このメソッドが呼び出されます：
```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
```

<Details>
<summary>イベント例（クリックして展開）</summary>
```javascript
// 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"
  }
}
```
</Details>
このケースではスクリーンを閉じることをお勧めします。

このメソッドはオブザーバーモードでは呼び出されません。詳細は [Android - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](android-present-paywall-builder-paywalls-in-observer-mode) をご参照ください。

#### 購入失敗 \{#failed-purchase\}
購入がエラーにより失敗した場合、このメソッドが呼び出されます。Google Play Billing のエラー（支払い制限、無効なプロダクト、ネットワーク障害）、トランザクション検証の失敗、およびシステムエラーが対象です。なお、ユーザーによるキャンセルはキャンセル結果を伴う `onPurchaseFinished` をトリガーし、保留中の支払いはこのメソッドをトリガーしません。

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>イベント例（クリックして展開）</summary>
```javascript
{
  "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"
  }
}
```
</Details>
このメソッドはオブザーバーモードでは呼び出されません。詳細については、[Android - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](android-present-paywall-builder-paywalls-in-observer-mode)トピックを参照してください。

#### ウェブ決済ナビゲーションの完了 \{#finished-web-payment-navigation\}

このメソッドは、特定のプロダクトの[ウェブペイウォール](web-paywall)を開こうとした後に呼び出されます。ナビゲーションの成功・失敗にかかわらず呼び出されます。

```kotlin showLineNumbers title="Kotlin"
public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}
```
**パラメーター：**

| パラメーター | 説明 |
|:------------|:-----|
| **product** | ウェブペイウォールが開かれた `AdaptyPaywallProduct`。`null` の場合があります。 |
| **error** | ウェブペイウォールのナビゲーションに失敗した場合は `AdaptyError` オブジェクト、成功した場合は `null`。 |

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
// 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"
    }
  }
}
```
</Details>
#### 購入の復元成功 \{#successful-restore\}

購入の復元が成功すると、このメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "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"
      }
    ]
  }
}
```
</Details>

ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることを推奨します。確認方法については、[サブスクリプションの状態](android-listen-subscription-changes) を参照してください。

#### 復元の失敗 \{#failed-restore\}
`Adapty.restorePurchases()` が失敗した場合、このメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>

```javascript
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}
```
</Details>

#### サブスクリプションのアップグレード \{#upgrade-subscription\}
ユーザーが既存のサブスクリプションがアクティブな状態で新しいサブスクリプションを購入しようとした場合、このメソッドをオーバーライドして新しい購入の処理方法を制御できます。次の2つのオプションがあります：
1. **現在のサブスクリプションを新しいものに置き換える:**
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(
        AdaptyPurchaseParameters.Builder()
            .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...))
            .build()
    )
    return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
2. **両方のサブスクリプションを維持する**（新しいものを別途追加する）：
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty)
    return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
:::note
このメソッドをオーバーライドしない場合、デフォルトの動作では両方のサブスクリプションがアクティブな状態を維持します（`AdaptyPurchaseParameters.Empty`を使用した場合と同じ動作です）。
:::

必要に応じて、追加の購入パラメーターを設定することもできます：
```kotlin
AdaptyPurchaseParameters.Builder()
    .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // optional - for replacing current subscription
    .withOfferPersonalized(true) // optional - if using personalized pricing
    .build()
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "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"
  }
}
```
</Details>
### データ取得とレンダリング \{#data-fetching-and-rendering\}

#### プロダクト読み込みエラー \{#product-loading-errors\}

初期化時にプロダクトを渡さない場合、AdaptyUI は必要なオブジェクトをサーバーから自動的に取得します。この操作が失敗した場合、AdaptyUI は次のメソッドを呼び出してエラーを報告します。

```kotlin showLineNumbers title="Kotlin"
public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}
```
</Details>

`true` を返すと、AdaptyUI は 2 秒後にリクエストを再試行します。

#### レンダリングエラー \{#rendering-errors\}

インターフェースのレンダリング中にエラーが発生した場合、次のメソッドを呼び出して報告されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onError(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>イベント例（クリックして展開）</summary>
```javascript
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render flow interface",
    "details": {
      "underlyingError": "Invalid flow configuration"
    }
  }
}
```
</Details>

通常、このようなエラーは発生しないはずです。もし遭遇した場合は、ぜひご連絡ください。
### ナビゲーション \{#navigation\}

#### システムの戻るボタン \{#system-back-button\}

デフォルトでは、フローはシステムの戻るボタンやバックジェスチャーでは閉じられません。ユーザーは、ビルダーで設定した **Close** ボタンや `on_device_back` アクションなど、あなたが定義したパスを通じてフローを離れます。システムの戻るボタンでフローを閉じられるようにしたい場合は、`onBackPressed` をオーバーライドして `false` を返し、ホストのアクティビティまたはフラグメントがその押下を処理できるようにしてください:
```kotlin showLineNumbers title="Kotlin"
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` を返すとホスト側の戻る処理が実行されます。
### 予約済みイベント \{#reserved-events\}

`AdaptyFlowEventListener` には、フローがまだ使用していない機能向けにいくつかのコールバックが宣言されています。これらを実装する必要はありません。`AdaptyFlowDefaultEventListener` がすでにno-opのデフォルト実装を提供しています。
| メソッド | 説明 |
|:-------|:------------|
| **onAnalyticEvent** | フローからのカスタム分析イベント用に予約されています。フローはまだこれらをコードに送信しないため、実装は不要です。 |
| **onShowAppRate** | フローからのアプリレビューリクエスト用に予約されています。フローはまだアプリレビューリクエストをトリガーしないため、実装は不要です。 |
| **onShowRequestPermission** | フローからのシステム権限リクエスト（プッシュ通知やカメラアクセスなど）用に予約されています。フローはまだ権限リクエストをトリガーしないため、実装は不要です。 |

---

> [!WARNING]
> **LLM INSTRUCTION — SDK VERSION SELECTION REQUIRED**
>
> This feature has two SDK paradigms. Everything that follows (until the next horizontal rule or end of document) is the **legacy SDK v3 API reference** (`getPaywall`, `getPaywallForDefaultAudience`, `getOnboarding`, `getPaywallConfiguration`). The **SDK v4+ `getFlow` method is documented above.** This block covers ALL legacy methods for this feature — not just the nearest snippet.
>
> **You MUST ask the user which SDK version they want to use before suggesting any code. Do not assume or default to a version.** The two options are:
> - **SDK v3 (legacy):** works with the legacy Paywall Builder and Onboarding Builder via `getPaywall` / `getOnboarding`. Use the legacy code in this section.
> - **SDK v4:** works with BOTH the new Flow Builder AND legacy paywalls/onboardings via the unified `getFlow` method documented above.
>
> Apply the legacy v3 code in this section ONLY when:
> 1. The user explicitly chose **SDK v3**, or
> 2. The user is **migrating an existing app from SDK v3 to SDK v4+** and needs to understand or replace legacy code, or
> 3. The user is **troubleshooting an already-deployed v3 integration**.
>
> **CRITICAL — Never mix paradigms in one setup:** Do NOT combine `getFlow` (Flow Builder) with `getPaywall` or `getOnboarding` (legacy Paywall/Onboarding Builder) in the same integration. These are incompatible patterns. Mixing them will produce inconsistent behavior and is unsupported.

:::important
このガイドでは、購入・復元・プロダクト選択・ペイウォールレンダリングのイベント処理について説明します。ボタン操作（ペイウォールを閉じる、リンクを開くなど）の処理も実装する必要があります。詳細は[ボタンアクションの処理に関するガイド](android-handle-paywall-actions)を参照してください。
:::
[ペイウォールビルダー](adapty-paywall-builder)で設定したペイウォールは、購入や復元のために追加のコードを書く必要はありません。ただし、アプリが対応できるイベントをいくつか生成します。これらのイベントには、ボタン操作（閉じるボタン、URL、プロダクト選択など）や、ペイウォール上で行われた購入関連アクションの通知が含まれます。これらのイベントへの対応方法については、以下をご覧ください。

:::warning
このガイドは、Adapty SDK v3.0以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。
:::

:::tip

Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか？ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。

:::
購入画面で発生するプロセスを制御・監視したい場合は、`AdaptyUiEventListener` のメソッドを実装してください。

一部のケースでデフォルトの動作をそのまま使いたい場合は、`AdaptyUiDefaultEventListener` を継承し、変更したいメソッドだけをオーバーライドできます。

以下は `AdaptyUiDefaultEventListener` のデフォルト実装です。
### ユーザーが生成するイベント \{#user-generated-events\}

#### プロダクトの選択 \{#product-selection\}

ユーザーまたはシステムによってプロダクトが購入のために選択されると、次のメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>

#### 購入の開始 \{#started-purchase\}

ユーザーが購入プロセスを開始すると、このメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>

このメソッドはオブザーバーモードでは呼び出されません。詳細は [Android - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](android-present-paywall-builder-paywalls-in-observer-mode) を参照してください。

#### 購入の成功・キャンセル・保留 \{#successful-canceled-or-pending-purchase\}

購入が成功した場合、このメソッドが呼び出されます：
```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
// 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"
  }
}
```
</Details>
その場合はスクリーンを閉じることを推奨します。

このメソッドはObserverモードでは呼び出されません。詳細は[Android - ObserverモードでのペイウォールビルダーペイウォールをPresent](android-present-paywall-builder-paywalls-in-observer-mode)トピックを参照してください。

#### 購入失敗 \{#failed-purchase\}
購入がエラーにより失敗した場合、このメソッドが呼び出されます。これには、Google Play Billing のエラー（支払い制限、無効なプロダクト、ネットワーク障害）、トランザクション検証の失敗、およびシステムエラーが含まれます。なお、ユーザーがキャンセルした場合はキャンセル結果とともに `onPurchaseFinished` がトリガーされ、保留中の支払いはこのメソッドをトリガーしません。

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>イベント例（クリックして展開）</summary>
```javascript
{
  "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"
  }
}
```
</Details>
このメソッドはオブザーバーモードでは呼び出されません。詳細については、[Android - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](android-present-paywall-builder-paywalls-in-observer-mode)を参照してください。

#### ウェブ決済ナビゲーションの完了 \{#finished-web-payment-navigation\}

このメソッドは、特定のプロダクトの[ウェブペイウォール](web-paywall)を開こうとした後に呼び出されます。ナビゲーションの成功・失敗に関わらず呼び出されます。

```kotlin showLineNumbers title="Kotlin"
public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}
```
**パラメーター：**

| パラメーター | 説明                                                                                        |
|:------------|:--------------------------------------------------------------------------------------------|
| **product** | ウェブペイウォールが開かれた `AdaptyPaywallProduct`。`null` の場合があります。                     |
| **error**   | ウェブペイウォールのナビゲーションに失敗した場合は `AdaptyError` オブジェクト、成功した場合は `null`。 |

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
// 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"
    }
  }
}
```
</Details>
#### 購入のリストア成功 \{#successful-restore\}

購入のリストアが成功した場合、このメソッドが呼び出されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "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"
      }
    ]
  }
}
```
</Details>

ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることをお勧めします。確認方法については、[サブスクリプションのステータス](android-listen-subscription-changes) をご覧ください。

#### 復元の失敗 \{#failed-restore\}
`Adapty.restorePurchases()` が失敗した場合、このメソッドが呼び出されます:

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>

```javascript
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}
```
</Details>

#### サブスクリプションのアップグレード \{#upgrade-subscription\}
<Tabs groupId="current-os" queryString>
<TabItem value="new" label="SDK version 3.10.0 以降" default>

ユーザーが既存のサブスクリプションがアクティブな状態で新しいサブスクリプションを購入しようとした場合、このメソッドをオーバーライドすることで新しい購入の処理方法を制御できます。2つのオプションがあります：
1. **現在のサブスクリプションを新しいものに置き換える：**
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback,
): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(
        AdaptyPurchaseParameters.Builder()
            .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...))
            .build()
    )
    return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
2. **両方のサブスクリプションを保持する**（新しいものを別途追加する）:
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback,
): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty)
    return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
:::note
このメソッドをオーバーライドしない場合、デフォルトの動作では両方のサブスクリプションがアクティブに保たれます（`AdaptyPurchaseParameters.Empty` を使用した場合と同等です）。
:::

追加の購入パラメータが必要な場合は、以下のように設定できます：
```kotlin
AdaptyPurchaseParameters.Builder()
    .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // optional - for replacing current subscription
    .withOfferPersonalized(true) // optional - if using personalized pricing
    .build()
```

</TabItem>
<TabItem value="old" label="SDK version earlier than 3.10.0" default>
別のサブスクリプションがまだアクティブな状態で新しいサブスクリプションが購入された場合、現在のものを新しいものに置き換えるにはこのメソッドをオーバーライドしてください。アクティブなサブスクリプションをそのまま維持し、新しいものを別途追加する場合は、`onSubscriptionUpdateParamsReceived(null)` を呼び出してください。

```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingSubscriptionUpdateParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback,
) {
    onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...))
}
```
</TabItem>
</Tabs>

<Details>
<summary>イベント例（クリックして展開）</summary>

```javascript
{
  "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"
  }
}
```
</Details>
### データの取得とレンダリング \{#data-fetching-and-rendering\}

#### プロダクト読み込みエラー \{#product-loading-errors\}

初期化時にプロダクトを渡さない場合、AdaptyUI は必要なオブジェクトをサーバーから自動的に取得します。この操作が失敗した場合、AdaptyUI は以下のメソッドを呼び出してエラーを報告します：

```kotlin showLineNumbers title="Kotlin"
public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
```

<Details>
<summary>イベント例（クリックして展開）</summary>
```javascript
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}
```
</Details>

`true` を返すと、AdaptyUI は 2 秒後にリクエストを再試行します。

#### レンダリングエラー \{#rendering-errors\}

インターフェースのレンダリング中にエラーが発生した場合、このメソッドが呼び出されてエラーが通知されます：

```kotlin showLineNumbers title="Kotlin"
public override fun onRenderingError(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>イベントの例（クリックして展開）</summary>
```javascript
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}
```
</Details>

通常、このようなエラーは発生しないはずです。もし遭遇した場合は、ぜひご連絡ください。

---