# KMP - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-07-01T16:29:19.446Z Total files: 50 --- # File: kmp-sdk-overview --- --- title: "Kotlin Multiplatform SDK overview" description: "Learn about Adapty Kotlin Multiplatform SDK and its key features." --- [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-KMP.svg?style=flat&logo=kotlin)](https://github.com/adaptyteam/AdaptySDK-KMP/releases) Welcome! We're here to make in-app purchases a breeze 🚀 We've built the Adapty Kotlin Multiplatform SDK to take the headache out of in-app purchases so you can focus on what you do best – building amazing apps. Here's what we handle for you: - Handle purchases, receipt validation, and subscription management out of the box - Create and test paywalls without app updates - Get detailed purchase analytics with zero setup - cohorts, LTV, churn, and funnel analysis included - Keep the user subscription status always up to date across app sessions and devices - Integrate your app with marketing attribution and analytics services using just one line of code :::note Before diving into the code, you'll need to integrate Adapty with Google Play Console and set up products in the dashboard. Check out our [quickstart guide](quickstart) to get everything configured first. ::: ## Get started For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. Here's what we'll cover in the integration guide: 1. [Install & configure SDK](sdk-installation-kotlin-multiplatform): Add the SDK as a dependency to your project and activate it in the code. 2. [Enable purchases through paywalls](kmp-quickstart-paywalls): Set up the purchase flow so users can buy products. 3. [Check the subscription status](kmp-check-subscription-status): Automatically check the user's subscription state and control their access to paid content. 4. [Identify users (optional)](kmp-quickstart-identify): Associate users with their Adapty profiles to ensure their data is stored consistently across devices. ### See it in action Want to see how it all comes together? We've got you covered: - **Sample app**: Check out our [complete example](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) that demonstrates the full setup - **Video tutorial**: Follow along with our step-by-step implementation video below ## Main concepts Before diving into the code, let's get familiar with the key concepts that make Adapty work. The beauty of Adapty's approach is that only placements are hardcoded in your app. Everything else – products, paywall designs, pricing, and offers – can be managed flexibly from the Adapty dashboard without app updates: 1. [**Product**](product) - Anything available for purchase in your app – subscription, consumable product, or lifetime access. 2. [**Paywall**](paywalls) - The only way to retrieve products from Adapty and use it to its full power. We've designed it this way to make it easier to track how different product combinations affect your monetization metrics. A paywall in Adapty serves as both a specific set of your products and the visual configuration that accompanies them. 3. [**Placement**](placements) - A strategic point in your user journey where you want to show a paywall. Think of placements as the "where" and "when" of your monetization strategy. Common placements include: - `main` - Your primary paywall location - `onboarding` - Shown during the user onboarding flow - `settings` - Accessible from your app's settings Start with the basics like `main` or `onboarding` for your first integration, then [think about where else in your app users might be ready to purchase](choose-meaningful-placements). 4. [**Profile**](profiles-crm) - When users purchase a product, their profile is assigned an **access level** which you use to define access to paid features. --- # File: sdk-installation-kotlin-multiplatform --- --- title: "Adapty Kotlin Multiplatform SDK のインストールと設定" description: "Kotlin Multiplatform アプリ向けに Adapty SDK をインストールして設定する方法を説明します。" --- Adapty SDKは、モバイルアプリへのシームレスな統合を実現する2つの主要モジュールで構成されています。 - **Core Adapty**: Adaptyがアプリで正常に機能するために必要な必須SDKです。 - **AdaptyUI** (`io.adapty:adapty-kmp-ui`): Compose Multiplatformレンダリングレイヤー(`view.present()`)で[Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合に必要なモジュールです。プロジェクトでCompose Multiplatformを使用していない場合は、代わりにコアモジュールの[`createNativePaywallView`](kmp-present-paywalls#without-compose-multiplatform)および[`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform)を使用できます。 :::tip Adapty SDK がモバイルアプリにどのように統合されるか、実際の例を見てみたいですか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを示す[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)をご覧ください。 ::: 完全な実装のウォークスルーについては、以下の動画もご参照ください: ## 動作要件 \{#requirements\} Adapty Kotlin Multiplatform SDK は Xcode 16.2 以降に対応しています。 :::info SDK v3.17 以降、Adapty SDK はデフォルトで Google Play Billing Library v8.0.0 を使用します。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 ## GradleでAdapty SDKをインストールする \{#install-adapty-sdk-via-gradle\} Adapty SDKのGradleによるインストールは、AndroidとiOSの両方のアプリに必要です。 依存関係の設定方法を選択してください: - 標準Gradle: **モジュールレベル**の`build.gradle`に依存関係を追加する - プロジェクトで`.gradle.kts`ファイルを使用している場合は、**モジュールレベル**の`build.gradle.kts`に依存関係を追加する - バージョンカタログを使用している場合は、`libs.versions.toml`ファイルに依存関係を追加し、`build.gradle.kts`で参照する ```kotlin showLineNumbers kotlin { sourceSets { commonMain { dependencies { implementation libs.adapty.kmp } } } } ``` ```kotlin showLineNumbers kotlin { sourceSets { val commonMain by getting { dependencies { implementation(libs.adapty.kmp) } } } } ``` ```toml showLineNumbers // libs.versions.toml [versions] .. adapty-kmp = "" [libraries] .. adapty-kmp = { module = "io.adapty:adapty-kmp", version.ref = "adapty-kmp" } // build.gradle.kts kotlin { sourceSets { val commonMain by getting { dependencies { implementation(libs.adapty.kmp) } } } } ``` :::note Maven 関連のエラーが発生した場合は、Gradle スクリプトに `mavenCentral()` が含まれていることを確認してください。
追加方法の手順 プロジェクトの `settings.gradle` に `dependencyResolutionManagement` がない場合は、トップレベルの `build.gradle` のリポジトリ末尾に以下を追加してください: ```groovy showLineNumbers title="top-level build.gradle" allprojects { repositories { ... mavenCentral() } } ``` `dependencyResolutionManagement` がある場合は、`settings.gradle` の `dependencyResolutionManagement` セクション内の `repositories` に以下を追加してください: ```groovy showLineNumbers title="settings.gradle" dependencyResolutionManagement { ... repositories { ... google() mavenCentral() } } ```
::: ## Adapty SDK を有効化する \{#activate-adapty-sdk\} ### 基本セットアップ \{#basic-setup\} 初期化はできるだけ早い段階で追加してください。通常は、両プラットフォーム共通の Kotlin コード内で行います。 :::note Adapty SDK はアプリ内で一度だけ有効化すれば十分です。 ::: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` の完了を待ってください。詳細な順序については、[Kotlin Multiplatform SDK の呼び出し順序](kmp-sdk-call-order)を参照してください。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[App settings → General](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではありません)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::info - Adapty の初期化には必ずパブリック SDK キーを使用してください。シークレットキーは[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - SDK キーはアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: 次に、アプリにペイウォールを設定します: - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使う場合は、まず以下の[AdaptyUI モジュールを有効化](#activate-adaptyui-module-of-adapty-sdk)してから、[ペイウォールビルダーのクイックスタート](kmp-quickstart-paywalls)に進んでください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](kmp-quickstart-manual)を参照してください。 ## AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](kmp-present-paywalls)を使用するために **AdaptyUI** モジュールを有効化する場合は、設定に `.withActivateUI(true)` を追加してください。 :::info 重要 コード内では、AdaptyUI を有効化する前に、コアの Adapty モジュールを先に有効化する必要があります。 ::: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withActivateUI(true) // true for activating the AdaptyUI module .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` ## Proguard の設定(Android) \{#configure-proguard-android\} 本番環境でアプリを公開する前に、Proguard の設定に `-keep class com.adapty.** { *; }` を追加する必要がある場合があります。 ## オプション設定 \{#optional-setup\} ### ログ記録 \{#logging\} #### ログシステムのセットアップ \{#set-up-the-logging-system\} Adapty はエラーやその他の重要な情報をログに記録し、何が起きているかを把握できるようにします。利用可能なログレベルは以下のとおりです: | レベル | 説明 | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ | | `AdaptyLogLevel.ERROR` | エラーのみがログに記録されます。 | | `AdaptyLogLevel.WARN` | エラーと、致命的なエラーは引き起こさないものの注意が必要なSDKからのメッセージがログに記録されます。 | | `AdaptyLogLevel.INFO` | エラー、警告、およびさまざまな情報メッセージがログに記録されます。デフォルト値。 | | `AdaptyLogLevel.VERBOSE` | 関数呼び出しやAPIクエリなど、デバッグ時に役立つ可能性のある追加情報がログに記録されます。 | | `AdaptyLogLevel.DEBUG` | 内部デバッグデータを含む、最も詳細な情報がログに記録されます。 | Adapty を設定する前に、アプリでログレベルを設定できます: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withLogLevel(AdaptyLogLevel.VERBOSE) // recommended for development .build() ``` ### データポリシー \{#data-policies\} #### IPアドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adaptyモジュールを有効にする際、`ipAddressCollectionDisabled` を `true` に設定すると、ユーザーのIPアドレスの収集と共有を無効にできます。デフォルト値は `false` です。 このパラメーターは、ユーザーのプライバシーを強化する場合、GDPRやCCPAなどの地域データ保護規制に準拠する場合、またはIPベースの機能がアプリに不要な場合に不要なデータ収集を減らすために活用してください。 ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build() ``` #### 広告IDの収集と共有を無効にする \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際、広告識別子の収集を無効にするには `appleIdfaCollectionDisabled`(iOS)または `googleAdvertisingIdCollectionDisabled`(Android)を true に設定してください。デフォルト値は false です。 このパラメータは、App Store/Play Storeのポリシーに準拠するため、App Tracking Transparencyのプロンプト表示を避けるため、または広告IDに基づくアドバタイジングアトリビューションやアナリティクスがアプリに不要な場合に使用してください。 ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withGoogleAdvertisingIdCollectionDisabled(true) // Android only .withAppleIdfaCollectionDisabled(true) // iOS only .build() ``` #### AdaptyUI のメディアキャッシュ設定 \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUI はパフォーマンスの向上とネットワーク使用量の削減のために、メディア(画像や動画など)をキャッシュします。カスタム設定を提供することで、キャッシュの設定をカスタマイズできます。 `mediaCache` を使用して、デフォルトのキャッシュ設定を上書きします。 ```kotlin val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withMediaCacheConfiguration( AdaptyConfig.MediaCacheConfiguration( memoryStorageTotalCostLimit = 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit = Int.MAX_VALUE, diskStorageSizeLimit = 200 * 1024 * 1024 // 200 MB ) ) .build() ``` ### ローカルアクセスレベルの有効化(Android) \{#enable-local-access-levels-android\} デフォルトでは、Android では[ローカルアクセスレベル](local-access-levels)が無効になっています。有効にするには、`withLocalAccessLevelAllowed` を `true` に設定します: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withGoogleLocalAccessLevelAllowed(true) .build() ``` ### バックアップ復元時のデータ消去 \{#clear-data-on-backup-restore\} `withAppleClearDataOnBackup` を `true` に設定すると、アプリが iCloud バックアップから復元されたことを SDK が検出し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールなど、ローカルに保存されているすべての SDK データを削除します。その後、SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴や Adapty サーバー上のユーザーデータは変更されません。 ::: ```swift showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withAppleClearDataOnBackup(true) .build() ``` ## トラブルシューティング \{#troubleshooting\} #### Android バックアップルール(自動バックアップの設定) \{#android-backup-rules-auto-backup-configuration\} 一部のSDK(Adaptyを含む)には、独自のAndroid Auto Backup設定が含まれています。バックアップルールを定義する複数のSDKを使用している場合、Androidのマニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 よくあるエラーの症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note これらの変更は、Androidプラットフォームのディレクトリ(通常はプロジェクトの `android/` フォルダー内)で行う必要があります。 ::: この問題を解決するには、以下が必要です: - バックアップ関連の属性に対して、アプリの値を使用するようマニフェストマージャーに指示する。 - AdaptyのルールとほかのSDKのルールをマージしたバックアップルールファイルを作成する。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` ファイルのルートの `` タグに tools が含まれていることを確認してください: ```xml ... ``` #### 2. `` でバックアップ属性を上書きする \{#2-override-backup-attributes-in-application\} 同じ `AndroidManifest.xml` ファイルで、`` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml ... ``` いずれかのSDKが `android:allowBackup` も設定している場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージしたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} AndroidプロジェクトのAdaptyのルールとほかのSDKのルールを組み合わせた `res/xml/` ディレクトリにXMLファイルを作成します。AndroidはOSのバージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することで、アプリがサポートするすべてのAndroidバージョンとの互換性が確保されます。 :::note 以下の例では、サンプルのサードパーティSDKとしてAppsFlyerを使用しています。アプリで使用しているほかのSDKのルールに置き換えるか、追加してください。 ::: **Android 12以降**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" ``` **Android 11以前**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" :::important Kotlin Multiplatform プロジェクトでは、APK/AAB を生成する Android アプリケーションモジュール(例:`androidApp` または `app`)に以下の変更を適用してください: - マニフェスト:`androidApp/src/main/AndroidManifest.xml` - バックアップルール XML:`androidApp/src/main/res/xml/` ::: #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始するアクティビティが非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ったときに Android がそのアクティビティを誤って再生成または再利用することがあります。これにより、購入結果が失われたり、キャンセル扱いになったりする可能性があります。 購入が正常に機能するよう、購入フローを開始するアクティビティには `standard` または `singleTop` のみを使用し、他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始するアクティビティが `standard` または `singleTop` に設定されていることを確認してください: ```xml ``` --- # File: kmp-quickstart-paywalls --- --- title: "Kotlin Multiplatform SDKのペイウォールを使用してアプリ内課金を有効にする" description: "アプリ内サブスクリプション管理のためにAdaptyをセットアップするクイックスタートガイド。" --- アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定です。Adaptyでは、ペイウォールがプロダクトを取得する唯一の手段ですが、この設計によりアプリのコードを変更せずに商品内容、価格、プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内ではプレースメントIDで取得します。これにより、A/B テストの実施やユーザーごとに異なるペイウォールの表示が簡単になります。 Adaptyでは、アプリ内課金を有効にする3つの方法を提供しています。アプリの要件に応じていずれかを選択してください: | 実装方法 | 複雑さ | 適した場面 | |---------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応のペイウォールを作成](quickstart-paywalls)します。Adaptyが自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて裏側で処理します。 | | 手動作成のペイウォール | 🟡 中程度 | アプリコードでペイウォールUIを実装しますが、プロダクト提供の柔軟性を維持するためAdaptyからペイウォールオブジェクトを取得します。[ガイド](kmp-quickstart-manual)を参照してください。 | | オブザーバーモード | 🔴 難しい | 既に独自の購入処理インフラを持っており、それを引き続き使用したい場合。オブザーバーモードにはAdaptyでの制限があります。[記事](observer-vs-full-mode)を参照してください。 | :::important **以下の手順は、Adaptyペイウォールビルダーで作成したペイウォールの実装方法を示しています。** ペイウォールビルダーを使用しない場合は、[手動作成のペイウォールで購入を処理するガイド](kmp-making-purchases)を参照してください。 ::: Adaptyペイウォールビルダーで作成したペイウォールをアプリコードに表示するには、以下の手順だけが必要です: 1. **ペイウォールを取得する**:AdaptyからペイウォールのPaywallオブジェクトを取得します。 2. **ペイウォールを表示し、Adaptyが購入を処理する**:取得したペイウォールコンテナをアプリに表示します。 3. **ボタンアクションを処理する**:ペイウォール上のユーザー操作と、アプリの応答を関連付けます。たとえば、ユーザーがボタンをクリックしたときにリンクを開いたり、ペイウォールを閉じたりします。 ## 開始前の準備 \{#before-you-start\} 開始前に、以下の手順を完了してください: 1. Adapty ダッシュボードでアプリを[App Store](initial_ios)や[Google Play](initial-android)に接続します。 2. Adaptyで[プロダクトを作成](create-product)します。 3. [ペイウォールを作成してプロダクトを追加](create-paywall)します。 4. [プレースメントを作成してペイウォールを追加](create-placement)します。 5. アプリコードに[Adapty SDKをインストールして有効化](sdk-installation-kotlin-multiplatform)します。 :::tip これらの手順を最も素早く完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使用してペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定されたプレースメントに紐付けられています。プレースメントを使用することで、異なるオーディエンスに異なるペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adaptyペイウォールビルダーで作成したペイウォールを取得するには、以下の手順が必要です: 1. `getPaywall`メソッドを使用して[プレースメント](placements)IDから`paywall`オブジェクトを取得し、それがビルダーで作成されたペイウォールかどうかを確認します。 2. `createPaywallView`メソッドを使用してペイウォールのビュー設定を取得します。ビュー設定にはペイウォールを表示するために必要なUI要素とスタイリングが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。オンにしないと空のビュー設定が返され、ペイウォールが表示されません。 ::: ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (!paywall.hasViewConfiguration) { return@onSuccess } val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } .onError { error -> // handle the error } ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定を取得したら、数行追加するだけでペイウォールを表示できます。 デバイス画面にビジュアルなペイウォールを表示するには、まず設定を行う必要があります。`AdaptyUI.createPaywallView()`メソッドを呼び出してください: ```kotlin showLineNumbers val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() ``` ビューの作成が完了したら、デバイスの画面に表示できます。 :::tip ペイウォールの表示方法の詳細については、[ガイド](kmp-present-paywalls)を参照してください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォール内のボタンをクリックすると、Kotlin Multiplatform SDKが購入、復元、ペイウォールのクローズ、リンクの開封を自動的に処理します。 ただし、カスタムまたは事前定義されたIDを持つボタンについては、コード内でアクションを処理する必要があります。または、デフォルトの動作をオーバーライドしたい場合もあります。 たとえば、以下は閉じるボタンのデフォルトの動作です。コードに追加する必要はありませんが、必要な場合にどのように実装するかを確認できます。 :::tip ボタンの[アクション](kmp-handle-paywall-actions)と[イベント](kmp-handling-events)の処理方法については、ガイドをお読みください。 ::: ```kotlin showLineNumbers AdaptyUI.setPaywallsEventsObserver(object : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { AdaptyUIAction.CloseAction, AdaptyUIAction.AndroidSystemBackAction -> view.dismiss() } } }) ``` ## 次のステップ \{#next-steps\} ペイウォールをアプリに表示する準備ができました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を行い、ペイウォールからテスト購入が完了できることを確認してください。 次に、[ユーザーのアクセスレベルを確認](kmp-check-subscription-status)して、適切なユーザーにペイウォールを表示したり、有料機能へのアクセスを付与したりするようにしてください。 ## 完全な例 \{#full-example\} 以下は、これらの手順をアプリにまとめて統合する方法です。 ```kotlin showLineNumbers // Set up the observer for handling paywall actions AdaptyUI.setPaywallsEventsObserver(object : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> view.dismiss() } } }) // Get and display the paywall Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (!paywall.hasViewConfiguration) { // Use custom logic return@onSuccess } val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } .onError { error -> // handle the error } ``` --- # File: kmp-check-subscription-status --- --- title: "Kotlin Multiplatform SDKでサブスクリプションのステータスを確認する" description: "AdaptyでKotlin Multiplatformアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- ユーザーが有料コンテンツにアクセスできるかどうか、またはペイウォールを表示するかどうかを判断するには、プロファイル内の[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態にアクセスして、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ペイウォールや有料コンテンツをユーザーに表示するかどうかを決める際には、プロファイル内の[アクセスレベル](access-level)を確認します。方法は2つあります。 - アプリ起動時など、最新のプロファイルデータがすぐに必要な場合や強制的に更新したい場合は、`getProfile` を呼び出す。 - **プロファイルの自動更新**を設定して、サブスクリプションのステータスが変わるたびに自動的に更新されるローカルコピーを保持する。 ### プロファイルを取得する \{#get-profile\} サブスクリプションのステータスを確認するもっとも簡単な方法は、`getProfile` メソッドを使ってプロファイルにアクセスすることです。 ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access } .onError { error -> // handle the error } ``` ### サブスクリプションの更新を監視する \{#listen-to-subscription-updates\} アプリ内でプロファイルの更新を自動的に受け取るには、次のようにします。 1. `Adapty.setOnProfileUpdatedListener()` を使ってプロファイルの変更を監視する。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼び出されたときに更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```kotlin showLineNumbers class SubscriptionManager { private var currentProfile: AdaptyProfile? = null init { // Listen for profile updates Adapty.setOnProfileUpdatedListener { profile -> currentProfile = profile // Update UI, unlock content, etc. } } // Use stored profile instead of calling getProfile() fun hasAccess(): Boolean { return currentProfile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true } } ``` :::note Adaptyはアプリ起動時にプロファイル更新リスナーを自動的に呼び出し、デバイスがオフラインでもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールの表示や有料機能へのアクセス許可をすぐに判断する必要がある場合は、ユーザーのプロファイルを直接確認できます。この方法は、アプリ起動時、プレミアムセクションへの遷移時、特定のコンテンツ表示前といったシナリオで役立ちます。 ```kotlin showLineNumbers private fun checkAccessAndShowPaywall() { // First, check if user has access Adapty.getProfile() .onSuccess { profile -> val hasAccess = profile.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true if (!hasAccess) { // User doesn't have access, show paywall showPaywall() } else { // User has access, show premium content showPremiumContent() } } .onError { error -> // If we can't check access, show paywall as fallback showPaywall() } } private fun showPaywall() { // Get and display paywall using the KMP SDK Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (paywall.hasViewConfiguration) { val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } else { // Handle remote config paywall or show custom UI handleRemoteConfigPaywall(paywall) } } .onError { error -> // Handle paywall loading error showError("Unable to load paywall") } } private fun showPremiumContent() { // Show your premium content here // This is where you unlock paid features } ``` ## 次のステップ \{#next-steps\} サブスクリプションのステータスを追跡する方法を理解したら、次は[ユーザープロファイルの操作](kmp-quickstart-identify)を学んで、ユーザーが購入済みのコンテンツに確実にアクセスできるようにしましょう。 --- # File: kmp-quickstart-identify --- --- title: "Kotlin Multiplatform SDKでユーザーを識別する" description: "KMPでアプリ内サブスクリプション管理のためにAdaptyをセットアップするためのクイックスタートガイド。" --- :::important このガイドは、独自の認証システムをお持ちの方を対象としています。ここでは、既存の認証システムと連携するように、AdaptyでユーザープロファイルをAdaptyで管理する方法について説明します。 ::: ユーザーの購入履歴をどのように管理するかは、アプリの認証モデルによって異なります。 - アプリがバックエンド認証を使用せず、ユーザーデータを保存しない場合は、[匿名ユーザーに関するセクション](#anonymous-users)を参照してください。 - アプリにバックエンド認証がある(またはある予定の)場合は、[識別済みユーザーに関するセクション](#identified-users)を参照してください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティです。Adaptyが自動的に作成します。 - 匿名(**カスタマーユーザーIDなし**)または識別済み(**カスタマーユーザーIDあり**)のどちらかになります。 - **カスタマーユーザーID**を提供することで、Adaptyのプロファイルと内部の認証システムとを相互参照できます。 匿名ユーザーと識別済みユーザーの違いは次のとおりです。 | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入復元 | カスタマーユーザーIDを通じてデバイス間で購入履歴を維持 | | **プロファイル管理** | 再インストールのたびに新しいプロファイルを作成 | セッションとデバイスをまたいで同一プロファイルを使用 | | **データの永続性** | 匿名ユーザーのデータはアプリのインストールに紐付けられる | 識別済みユーザーのデータはアプリのインストールをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証がない場合、**アプリのコードで認証を処理する必要はありません**。 1. アプリの初回起動時にSDKがアクティベートされると、Adaptyは**ユーザーの新しいプロファイルを作成します**。 2. ユーザーがアプリ内で何かを購入すると、その購入は**ユーザーのAdaptyプロファイルおよびストアアカウントに関連付けられます**。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyはアクティベート時に**新しい匿名プロファイルを作成します**。 4. ユーザーが以前にアプリで購入している場合、SDKのアクティベート時にデフォルトで購入がApp Storeから自動的に同期されます。 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyのアナリティクスで[新規インストールとみなす基準を設定できる](general#4-installs-definition-for-analytics)ため、問題ありません。 匿名ユーザーの場合、インストール数は**デバイスID**でカウントする必要があります。この場合、再インストールを含め、デバイスへのアプリインストールがそれぞれ1回のインストールとしてカウントされます。 :::note バックアップからの復元は再インストールとは異なる動作をします。デフォルトでは、ユーザーがバックアップから復元した場合、SDKはキャッシュされたデータを保持し、新しいプロファイルは作成しません。この動作は`withAppleClearDataOnBackup`設定で変更できます。[詳細を確認する](sdk-installation-kotlin-multiplatform#clear-data-on-backup-restore)。 ::: ## 識別済みユーザー \{#identified-users\} ユーザーをアプリ内で識別するには2つの方法があります。 - [**ログイン/サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合、認証時に`identify()`をカスタマーユーザーIDとともに呼び出します。 - [**SDKアクティベーション時:**](#during-the-sdk-activation) アプリ起動時にすでにカスタマーユーザーIDが保存されている場合は、`activate()`の呼び出し時にそれを渡します。 :::important デフォルトでは、Adaptyが現在別のカスタマーユーザーIDに関連付けられているカスタマーユーザーIDからの購入を受け取った場合、アクセスレベルは共有されるため、両方のプロファイルが有料アクセスを持つことになります。この設定を変更して、有料アクセスを一方のプロファイルから他方に移行したり、共有を完全に無効にしたりすることができます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)をご覧ください。 ::: ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(たとえば、アプリへのログインやサインアップ後など)、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを以前に使用したことがない**場合、Adaptyは自動的に現在のプロファイルにリンクします。 - **このカスタマーユーザーIDでユーザーを以前に識別したことがある**場合、AdaptyはそのカスタマーユーザーIDに関連付けられたプロファイルを使用するよう切り替えます。 :::important カスタマーユーザーIDは各ユーザーで一意である必要があります。パラメータの値をハードコードすると、すべてのユーザーが同一人物とみなされます。 ::: 他のSDKメソッドを呼び出す前に、`identify`の完了(`onSuccess`コールバック)を待ってください。同時に呼び出すと、匿名プロファイルに処理が行われる可能性があります。[Kotlin Multiplatform SDKでの呼び出し順序](kmp-sdk-call-order)を参照してください。 ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` ### SDKアクティベーション時 \{#during-the-sdk-activation\} SDKをアクティベートする際にすでにカスタマーユーザーIDが分かっている場合、`identify`を別途呼び出す代わりに`activate`メソッドで渡すことができます。 カスタマーユーザーIDが分かっているにもかかわらず、アクティベーション後にのみ設定した場合、アクティベーション時にAdaptyが新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルに切り替わることになります。 既存のカスタマーユーザーID(以前に使用したもの)でも新しいものでも渡すことができます。新しいものを渡した場合、アクティベーション時に作成された新しいプロファイルが自動的にそのカスタマーユーザーIDにリンクされます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスのダッシュボードに影響しません。インストール数はデバイスIDに基づいてカウントされるためです。 デバイスIDは、デバイス上のストアからのアプリの単一のインストールを表し、アプリが再インストールされた場合にのみ再生成されます。 初回インストールか再インストールか、または既存のカスタマーユーザーIDが使用されているかどうかには依存しません。 プロファイルの作成(SDKのアクティベーション時またはログアウト時)、ログイン、またはアプリを再インストールせずにアップグレードしても、追加のインストールイベントは生成されません。 デバイスではなくユニークユーザーに基づいてインストール数をカウントしたい場合は、**App settings**に移動して[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build() ``` ### ユーザーのログアウト \{#log-users-out\} ユーザーのログアウトボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーをログアウトすると、そのユーザーのために新しい匿名プロファイルが作成されます。 ::: ```kotlin showLineNumbers Adapty.logout() .onSuccess { // successful logout } .onError { error -> // handle the error } ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用します。 ::: ### ログインなしでの購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリへのログイン前後の両方で購入できる場合、ログイン後もアクセスが維持されるように設定する必要があります。 1. ログアウト状態のユーザーが購入すると、Adaptyはその購入を匿名プロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルを使用するよう切り替わります。 - 新しいカスタマーユーザーIDの場合(たとえば、登録前に購入が行われた場合)、Adaptyは現在のプロファイルにカスタマーユーザーIDを割り当てるため、すべての購入履歴が維持されます。 - 既存のカスタマーユーザーIDの場合(カスタマーユーザーIDがすでにプロファイルにリンクされている場合)、プロファイルの切り替え後に実際のアクセスレベルを取得する必要があります。識別後すぐに[`getProfile`](kmp-check-subscription-status)を呼び出すか、[プロファイルの更新をリッスンする](kmp-check-subscription-status)ことでデータが自動的に同期されます。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内課金のロジックが実装できました!アプリの収益化がうまくいくことを願っています! Adaptyをさらに活用するために、以下のトピックも確認してください。 - [**テスト**](troubleshooting-test-purchases):すべてが期待どおりに動作することを確認する - [**インテグレーション**](configuration):マーケティングアトリビューションや分析サービスとわずか1行のコードで連携する - [**カスタムプロファイル属性の設定**](kmp-setting-user-attributes):ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/Bテストを実施したり、ユーザーに応じて異なるペイウォールを表示したりする --- # File: adapty-sdk-integration-skill-kmp --- --- title: "SDK統合スキルを使ってKotlin MultiplatformアプリにAdaptyを組み込む" description: "adapty-sdk-integrationスキルを使用して、AIコーディングツールでKotlin MultiplatformアプリにAdapty SDKをエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作をした場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor-kmp)を参照してください。AIツールが各ステージを適切なドキュメントとともに順を追って進められるよう設計されています。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-kmp --- --- title: "AIアシスタンスを使ってAdaptyをKotlin Multiplatformアプリに統合する" description: "Cursor、Context7、ChatGPT、Claude、またはその他のAIツールを使用して、Kotlin MultiplatformアプリにAdaptyを統合するためのステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使いながら、Kotlin MultiplatformアプリへのAdapty統合をステップバイステップで進めます。適切なAdaptyドキュメントを正しい順番でAIに渡していくことがポイントです。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## はじめる前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyのSDKコードを書く前に、ダッシュボードでいくつかの設定が必要です。インタラクティブなLLMスキルを使う方法と、ダッシュボードから手動で行う方法があります。 ### スキルを使う方法(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使うと、アプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントの設定をLLMから直接行えます。ダッシュボードを都度開く必要がありません。必要なのは、ダッシュボードで[ストアを接続する](integrate-payments)ことだけです。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行してください。各ステップを順番にガイドしてくれます。ストアの接続が必要なタイミングでは、ダッシュボードを開くよう案内されます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} すべて手動で設定したい場合は、コードを書く前に以下の手順を完了してください。ダッシュボードの値はLLMが自動で取得することはできないため、自分で用意する必要があります。 1. **アプリストアを接続する**: Adapty ダッシュボードで **App settings → General** に移動し、KMPアプリがApp StoreとGoogle Play両方を対象とする場合は両方接続してください。これは購入機能を動作させるために必要です。 [アプリストアを接続する](integrate-payments) 2. **Public SDK keyをコピーする**: Adapty ダッシュボードで **App settings → General** に移動し、**API keys** セクションを確認してください。コード上では、Adaptyの設定ビルダーに渡す文字列です。 3. **プロダクトを少なくとも1つ作成する**: Adapty ダッシュボードの **Products** ページで作成してください。コードからプロダクトを直接参照することはなく、Adaptyはペイウォール経由でプロダクトを配信します。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードの **Paywalls** ページでペイウォールを作成し、**Placements** ページでプレースメントに割り当ててください。コード上では、`Adapty.getPaywall("YOUR_PLACEMENT_ID")` に渡す文字列がプレースメントIDです。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページで各プロダクトに対して設定してください。コード上では `profile.accessLevels["premium"]?.isActive` で確認する文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで使えます。プロダクトによってアクセスできる機能が異なる場合(例: `basic` プランと `pro` プラン)は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip 5つすべて揃ったら、コードを書く準備ができています。LLMに「Public SDK keyはX、プレースメントIDはY」と伝えることで、正確な初期化コードとペイウォール取得コードを生成してもらえます。 ::: ### 準備が整ったら設定するもの \{#set-up-when-ready\} コーディングを始めるのに必須ではありませんが、統合が進むにつれて必要になるものです: - **A/B テスト**: **Placements** ページで設定できます。コードの変更は不要です。 [A/B テスト](ab-tests) - **追加のペイウォールとプレースメント**: 異なるプレースメントIDを使って `getPaywall` の呼び出しを追加してください。 - **アナリティクス連携**: **Integrations** ページで設定します。連携方法は各サービスによって異なります。[アナリティクス連携](analytics-integration)と[アトリビューション連携](attribution-integration)を参照してください。 ## AdaptyドキュメントをLLMに渡す \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com)は、LLMが最新のAdaptyドキュメントに直接アクセスできるMCPサーバーです。質問内容に応じて必要なドキュメントを自動的に取得するため、URLを手動で貼り付ける必要がありません。 Context7は **Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで利用できます。設定するには次のコマンドを実行してください: ``` npx ctx7 setup ``` エディタを自動検出してContext7サーバーを設定します。手動でセットアップする場合は[Context7 GitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定後は、プロンプトでAdaptyライブラリを参照できます: ``` Use the adaptyteam/adapty-docs library to look up how to install the Kotlin Multiplatform SDK ``` :::warning Context7を使えばドキュメントのリンクを手動で貼る手間は省けますが、実装の順序は重要です。以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めて、確実に動作させてください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはどれもプレーンテキストのMarkdownで取得できます。URLの末尾に `.md` を付けるか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例: [adapty-cursor-kmp.md](https://adapty.io/docs/ja/adapty-cursor-kmp.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステップには、「LLMに送る内容」ブロックに `.md` リンクが含まれています。 まとめて複数のドキュメントを渡したい場合は、下記の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} このガイドの残りの部分では、実装順にAdaptyの統合を進めます。各ステップにはLLMに送るドキュメント、完了時の確認事項、よくある問題を記載しています。 ### 統合を計画する \{#plan-your-integration\} コードを書き始める前に、LLMにプロジェクトを分析させて実装計画を立てましょう。AIツールにプランニングモードがある場合(CursorやClaude Codeのプランモードなど)、それを使うことでLLMがプロジェクト構造とAdaptyドキュメントの両方を読んでからコードを書いてくれます。 購入の実装方法をLLMに伝えてください。選択によって参照すべきガイドが変わります: - [**Adapty ペイウォールビルダー**](adapty-paywall-builder): Adaptyのノーコードビルダーでペイウォールを作成し、SDKが自動的にレンダリングします。 - [**手動作成のペイウォール**](kmp-making-purchases): 自分でペイウォールUIをコードで作成しますが、プロダクトの取得と購入処理にはAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラをそのまま使い、Adaptyはアナリティクスと連携のみに使います。 どれを選べばいいか迷ったら、[クイックスタートの比較表](kmp-quickstart-paywalls)を参照してください。 ### SDKのインストールと設定 \{#install-and-configure-the-sdk\} GradleでAdapty SDKの依存関係を追加し、Public SDK keyで有効化してください。これがすべての基盤になります。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-kotlin-multiplatform) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-kotlin-multiplatform.md ``` :::tip[チェックポイント] - **期待される結果:** アプリがビルドされ、起動します。Logcat(Android)またはXcodeコンソール(iOS)にAdaptyの有効化ログが表示されます。 - **注意点:** 「Public API key is missing」→ プレースホルダーをApp settingsの実際のキーに置き換えたか確認してください。 ::: ### ペイウォールの表示と購入処理 \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入の実装方法によって異なります。 進めながら都度サンドボックスで購入をテストしてください。最後まで待たないようにしましょう。設定方法は[サンドボックスでの購入テスト](test-purchases-in-sandbox)を参照してください。 **ガイド:** - [ペイウォールを使って購入を有効化する(クイックスタート)](kmp-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](kmp-get-pb-paywalls) - [ペイウォールを表示する](kmp-present-paywalls) - [ペイウォールのイベントを処理する](kmp-handling-events) - [ボタンアクションに対応する](kmp-handle-paywall-actions) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-quickstart-paywalls.md - https://adapty.io/docs/ja/kmp-get-pb-paywalls.md - https://adapty.io/docs/ja/kmp-present-paywalls.md - https://adapty.io/docs/ja/kmp-handling-events.md - https://adapty.io/docs/ja/kmp-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトとともにペイウォールが表示されます。プロダクトをタップするとサンドボックスの購入ダイアログが表示されます。 - **注意点:** ペイウォールが空または `getPaywall` エラーが出る → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが設定されているか確認してください。 ::: **ガイド:** - [カスタムペイウォールで購入を有効化する(クイックスタート)](kmp-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-kmp) - [リモートコンフィグで設計したペイウォールをレンダリングする](present-remote-config-paywalls-kmp) - [購入を行う](kmp-making-purchases) - [購入を復元する](kmp-restore-purchase) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-kmp.md - https://adapty.io/docs/ja/present-remote-config-paywalls-kmp.md - https://adapty.io/docs/ja/kmp-making-purchases.md - https://adapty.io/docs/ja/kmp-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示されます。プロダクトをタップするとサンドボックスの購入ダイアログが表示されます。 - **注意点:** プロダクトの配列が空 → ダッシュボードのペイウォールにプロダクトが設定されているか、プレースメントにオーディエンスが設定されているか確認してください。 ::: **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-kmp) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-kmp) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-kmp.md - https://adapty.io/docs/ja/report-transactions-observer-mode-kmp.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行った後、トランザクションがAdaptyダッシュボードの **Event Feed** に表示されます。 - **注意点:** イベントが表示されない → Adaptyへのトランザクション報告が実装されているか、両ストアのサーバー通知が設定されているか確認してください。 ::: ### サブスクリプションのステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクティブなアクセスレベルを確認してプレミアムコンテンツを制限します。 **ガイド:** [サブスクリプションのステータスを確認する](kmp-check-subscription-status) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックス購入後、`profile.accessLevels["premium"]?.isActive` が `true` を返します。 - **注意点:** 購入後に `accessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが設定されているか確認してください。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyプロファイルに紐付けて、デバイスをまたいで購入情報を引き継げるようにします。 :::important アプリに認証機能がない場合は、このステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](kmp-quickstart-identify) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty.identify("your-user-id")` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示されます。 - **注意点:** 匿名プロファイルへのアトリビューションを避けるため、`identify` はアクティベーション後、ペイウォールの取得前に呼び出してください。 ::: ### リリースの準備をする \{#prepare-for-release\} サンドボックスで統合の動作確認ができたら、リリースチェックリストを確認してすべて本番環境に対応しているか確認しましょう。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送る内容: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** すべてのチェックリスト項目が確認済み:ストアの接続、サーバー通知、購入フロー、アクセスレベルの確認、プライバシー要件。 - **注意点:** サーバー通知が未設定 → **App settings → iOS SDK** でApp Store Server Notificationsを設定し、**App settings → Android SDK** でGoogle Play Real-Time Developer Notificationsを設定してください。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個別のページを超えてLLMにより広いコンテキストを提供したい場合は、Adaptyのすべてのドキュメントをリスト化または統合したインデックスファイルを用意しています: - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): すべてのページを `.md` リンク付きでリスト化しています。LLMがウェブサイトにアクセスしやすくするための[新たな標準](https://llmstxt.org/)です。一部のAIエージェント(ChatGPTなど)では、`llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyのドキュメントサイト全体を1つのファイルにまとめたものです。非常に大きいため、全体像が必要なときだけ使用してください。 - Kotlin Multiplatform専用の [`kmp-llms.txt`](https://adapty.io/docs/ja/kmp-llms.txt) と [`kmp-llms-full.txt`](https://adapty.io/docs/ja/kmp-llms-full.txt): サイト全体と比べてトークンを節約できるプラットフォーム別サブセットです。 --- # File: kmp-paywalls --- --- title: "Paywalls in Kotlin Multiplatform SDK" description: "Learn how to work with paywalls in your Kotlin Multiplatform app with Adapty SDK." --- ## Display paywalls ### Adapty Paywall Builder :::tip To get started with the Adapty Paywall Builder paywalls quickly, see our [quickstart guide](kmp-quickstart-paywalls). ::: ### Implement paywalls manually For more guides on implementing paywalls and handling purchases manually, see the [category](kmp-implement-paywalls-manually). ## Useful features --- # File: kmp-get-pb-paywalls --- --- title: "Kotlin Multiplatform SDKでペイウォールビルダーのペイウォールと設定を取得する" description: "Kotlin MultiatformアプリのAdaptyでPBペイウォールを取得し、サブスクリプションを管理する方法を学びます。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアルデザインを作成](adapty-paywall-builder)したら、モバイルアプリで表示できます。最初のステップは、プレースメントに紐づいたペイウォールと、以下で説明するビュー設定を取得することです。 このトピックはペイウォールビルダーでカスタマイズしたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する](fetch-paywalls-and-products-kmp)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 :::
モバイルアプリでペイウォールの表示を始める前に(クリックして展開) 1. Adapty ダッシュボードで[プロダクトを作成](create-product)する。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトを追加](create-paywall)する。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを追加](create-placement)する。 4. モバイルアプリに[Adapty SDK](sdk-installation-kotlin-multiplatform)をインストールする。
## ペイウォールビルダーで作成したペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーでペイウォールをデザイン](adapty-paywall-builder)した場合、ユーザーに表示するためのレンダリングコードをアプリに書く必要はありません。このようなペイウォールには、表示内容と表示方法の両方が含まれています。ただし、プレースメントを通じてIDを取得し、ビュー設定を取得したうえで、モバイルアプリで表示する必要があります。 パフォーマンスを最適化するには、ペイウォールとその[ビュー設定](kmp-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードが完了するよう時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します。 ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子。マイナス(**-**)で区切られた1つまたは2つのサブタグで構成される言語コードです。最初のサブタグは言語、2番目はリージョンを表します。

例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。

ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。

| | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新データを取得できるため、この設定を推奨します。

ただし、ユーザーが不安定なインターネット環境にいる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。

キャッシュはアプリを再起動しても保持され、アプリの再インストールや手動クリーンアップ時のみクリアされます。

Adapty SDKはペイウォールを2層でローカルに保存します。上記の定期更新キャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、CDNを使用してペイウォールを高速に取得し、CDNが到達不可能な場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な状況でも信頼性を確保しながら、常に最新バージョンのペイウォールを提供するよう設計されています。

| | **loadTimeout** | デフォルト: 5秒 |

このメソッドのタイムアウト時間を制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。

内部的に複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間より若干遅くタイムアウトすることがあります。

Kotlin Multiplatformでは、`TimeInterval` を拡張関数(例:`import com.adapty.utils.seconds` の `.seconds` を使った `5.seconds`)または `TimeInterval.seconds(5)` で作成できます。制限を設けない場合は `TimeInterval.INFINITE` を使用してください。

| レスポンスパラメーター: | パラメーター | 説明 | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/) オブジェクト。 | ## ペイウォールビルダーで作成したペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーの **Show on device** トグルが有効になっていることを確認してください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得したら、`ViewConfiguration` が含まれているか確認してください。これはペイウォールビルダーで作成されたことを示します。`ViewConfiguration` が存在する場合はペイウォールビルダーのペイウォールとして扱い、存在しない場合は[リモートコンフィグペイウォールとして処理](present-remote-config-paywalls-kmp)してください。 ビュー設定を読み込むには `createPaywallView` メソッドを使用します。 ```kotlin showLineNumbers if (paywall.hasViewConfiguration) { AdaptyUI.createPaywallView( paywall = paywall, loadTimeout = 5.seconds, preloadProducts = true ).onSuccess { paywallView -> // use paywallView }.onError { error -> // handle the error } } else { // use your custom logic } ``` | パラメーター | 必須/任意 | 説明 | | :--------------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | 必須 | 目的のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **loadTimeout** | 任意 | このメソッドのタイムアウト時間を制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。内部的に複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間より若干遅くタイムアウトすることがあります。`kotlin.time.Duration.Companion` の `5.seconds` などの拡張関数を使用できます。 | | **preloadProducts** | 任意 | パフォーマンス向上のためにプロダクトをプリロードするには `true` に設定します。有効にすると、プロダクトが事前に読み込まれ、ペイウォールの表示にかかる時間が短縮されます。 | | **productPurchaseParams** | 任意 | [`AdaptyProductIdentifier`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-product-identifier/) から [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) へのマップ。ペイウォール内の個別プロダクトに対して、パーソナライズドオファーやサブスクリプション更新パラメーターなど、購入固有のパラメーターを設定するために使用します。 | :::note 複数の言語を使用している場合は、[ペイウォールビルダーのローカライズ](add-paywall-locale-in-adapty-paywall-builder)を追加する方法を確認してください。 ::: 読み込みが完了したら、[ペイウォールを表示](kmp-present-paywalls)します。 ## デフォルトオーディエンス向けのペイウォールを取得して高速化する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得できるため、この処理を高速化することを気にする必要はありません。ただし、オーディエンスやペイウォールが多数あり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に期待以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を確保したい場合があります。 この問題に対処するため、指定されたプレースメントの **All Users** オーディエンス向けペイウォールを取得する `getPaywallForDefaultAudience` メソッドを使用できます。ただし、推奨されるアプローチは上記の[ペイウォール情報を取得する](#fetch-paywall-designed-with-paywall-builder)セクションで説明した `getPaywall` メソッドを使用することであることを理解しておくことが重要です。 :::warning `getPaywall` の使用を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題**: 現在と将来のアプリバージョンで異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇する可能性を受け入れるかのどちらかになります。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになり、国、マーケティングのアトリビューション、独自のカスタム属性に基づくパーソナライズされたターゲティングが失われます。 ペイウォールの取得を高速化するためにこれらの欠点を受け入れる場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライズ](add-remote-config-locale)の識別子。マイナス(**-**)で区切られた1つまたは複数のサブタグで構成される言語コードです。最初のサブタグは言語、2番目はリージョンを表します。

例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。

ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。

| | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新データを取得できるため、この設定を推奨します。

ただし、ユーザーが不安定なインターネット環境にいる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。

キャッシュはアプリを再起動しても保持され、アプリの再インストールや手動クリーンアップ時のみクリアされます。

| ## アセットをカスタマイズする \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には事前定義されたID(`hero_image` と `hero_video`)があります。カスタムアセットバンドルでは、これらの要素をIDで指定して動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定](custom-media)する必要があります。 たとえば、以下のことができます: - 一部のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像の読み込み中にローカルのプレビュー画像を表示する。 - 動画再生前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty SDKをバージョン3.7.0以上に更新してください。 ::: マップを使用してカスタムアセットを提供する例を示します: :::info Kotlin Multiplatform SDKはローカルアセットのみをサポートしています。リモートコンテンツの場合は、カスタムアセットで使用する前にアセットをダウンロードしてローカルにキャッシュしてください。 ::: ```kotlin showLineNumbers // Import generated Res class for accessing resources viewModelScope.launch { // Get URIs for bundled resources using Res.getUri() val heroImagePath = Res.getUri("files/images/hero_image.png") val demoVideoPath = Res.getUri("files/videos/demo_video.mp4") // Or read image as byte data val imageByteData = Res.readBytes("files/images/avatar.png") // Create custom assets map val customAssets: Map = mapOf( // Load image from app resources (bundled with the app) // Files should be placed in commonMain/composeResources/files/ "hero_image" to AdaptyCustomAsset.localImageResource( path = heroImagePath ), // Or use image byte data "avatar" to AdaptyCustomAsset.localImageData( data = imageByteData ), // Load video from app resources "demo_video" to AdaptyCustomAsset.localVideoResource( path = demoVideoPath ), // Or use a video file from device storage "intro_video" to AdaptyCustomAsset.localVideoFile( path = "/path/to/local/video.mp4" ), // Apply custom brand colors "brand_primary" to AdaptyCustomAsset.color( colorHex = "#FF6B35" ), // Create gradient background "card_gradient" to AdaptyCustomAsset.linearGradient( colors = listOf("#1E3A8A", "#3B82F6", "#60A5FA"), stops = listOf(0.0f, 0.5f, 1.0f) ) ) // Use custom assets when creating paywall view AdaptyUI.createPaywallView( paywall = paywall, customAssets = customAssets ).onSuccess { paywallView -> // Present the paywall with custom assets paywallView.present() }.onError { error -> // Handle the error - paywall will fall back to default appearance } } ``` :::note アセットが見つからない場合や読み込みに失敗した場合、ペイウォールはペイウォールビルダーで設定されたデフォルトの外観にフォールバックします。 ::: --- # File: kmp-present-paywalls --- --- title: "Kotlin Multiplatform - 新しいペイウォールビルダーのペイウォールを表示する" description: "Kotlin Multiplatformでペイウォールを表示して効果的なマネタイズを実現する方法を学びましょう。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでレンダリングをゼロから実装する必要はありません。ペイウォールには「何を表示するか」と「どのように表示するか」の情報が含まれています。 :::warning このガイドは**新しいペイウォールビルダーのペイウォール**専用です。リモートコンフィグで設計されたペイウォールや [Observer モード](observer-vs-full-mode) では、ペイウォールの表示方法が異なります。 **リモートコンフィグのペイウォール**を表示する方法については、[リモートコンフィグで設計されたペイウォールをレンダリングする](present-remote-config-paywalls-kmp) をご覧ください。 ::: Adapty Kotlin Multiplatform SDK では、ペイウォールを表示する方法が 2 つあります。 - **Compose Multiplatform を使用する** - **Compose Multiplatform を使用しない** ## Compose Multiplatform を使用する \{#with-compose-multiplatform\} ペイウォールを表示するには、[`createPaywallView`](kmp-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) メソッドで作成した `view` に対して `view.present()` メソッドを呼び出します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`createPaywallView` を再度呼び出して新しい `view` インスタンスを作成してください。 :::warning `view` を再作成せずに使い回すとエラーが発生する場合があります。 ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createPaywallView(paywall = paywall).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### ダイアログを表示する \{#show-dialog\} Android でペイウォールビューが表示されている場合は、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では通常のアラートがペイウォールビューの背後に表示されてしまい、ユーザーから見えなくなります。このメソッドを使うことで、すべてのプラットフォームでペイウォールの上にダイアログが正しく表示されます。 ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { view.showDialog( title = "Close paywall?", content = "You will lose access to exclusive offers.", primaryActionTitle = "Stay", secondaryActionTitle = "Close" ).onSuccess { action -> if (action == AdaptyUIDialogActionType.SECONDARY) { // User confirmed - close the paywall view.dismiss() } // If primary - do nothing, user stays }.onError { error -> // handle the error } } ``` ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメータを渡すことで、iOS でのペイウォールの表示スタイルを設定できます。このパラメータには `AdaptyUIIOSPresentationStyle.FULLSCREEN`(デフォルト)または `AdaptyUIIOSPresentationStyle.PAGESHEET` を指定できます。 ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createPaywallView(paywall = paywall).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ## Compose Multiplatform を使用しない \{#without-compose-multiplatform\} :::note `createNativePaywallView` はコアモジュール `io.adapty:adapty-kmp` に含まれています。プロジェクトで Compose Multiplatform を使用していない場合、`io.adapty:adapty-kmp-ui` への依存は不要です。 ::: Compose Multiplatform を使用せずにペイウォールを埋め込むには、`createNativePaywallView` を呼び出します。このメソッドはレイアウトに追加できる `AdaptyNativePaywallView` を返します。 ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` KMP インターフェースのデフォルトメソッドは Swift では `@required` になるため、Swift から直接 `AdaptyUIPaywallsEventsObserver` を実装することはできません。まず `iosMain` にオープンな基底クラスを宣言してください。 ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BasePaywallObserver : AdaptyUIPaywallsEventsObserver ``` 次に Swift でサブクラスを作成し、必要なメソッドのみオーバーライドします。 ```swift showLineNumbers title="Swift" class MyPaywallObserver: BasePaywallObserver { override func paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: any AdaptyUIAction) { if action is AdaptyUIActionCloseAction { // remove nativeView from your view hierarchy } } } let nativeView = AdaptyUI.shared.createNativePaywallView( paywall: paywall, observer: MyPaywallObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` ### ビューを破棄する \{#dispose-the-view\} レイアウトからビューを削除する際は `dispose()` を呼び出してください。これによりイベントリスナーの登録が解除され、内部リソースが解放されます。 ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` ## カスタムタグ \{#custom-tags\} カスタムタグを使うと、シナリオごとに別々のペイウォールを作らずに済みます。ユーザーデータに応じて動的に変化するペイウォールを 1 つ用意するイメージです。たとえば、"Hello!" という汎用的な文言の代わりに、"Hello, John!" や "Hello, Ann!" のようにユーザーに合わせた挨拶を表示できます。 カスタムタグの活用例を以下に示します。 - ペイウォールにユーザーの名前やメールアドレスを表示する。 - 売上促進のために現在の曜日を表示する(例:「Happy Thursday」)。 - 販売中のプロダクトに関するパーソナライズされた情報(フィットネスプログラムの名称や VoIP アプリの電話番号など)を追加する。 カスタムタグを使うと、様々な状況に柔軟に対応できるペイウォールを作成でき、アプリのインターフェースをよりパーソナライズして魅力的にできます。 :::warning AdaptyUI SDK の古いバージョンを使用しているユーザーを対象とするケースなど、カスタムタグの置換先が不明な場合があります。そのため、未知のカスタムタグを含む行を置き換えるフォールバックテキストを必ず設定してください。設定しないと、タグがコード(``)としてそのまま表示されてしまいます。 ::: ペイウォールでカスタムタグを使用するには、ペイウォールビューを作成する際に渡します。 ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) AdaptyUI.createPaywallView( paywall = paywall, customTags = customTags ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, customTags = customTags, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativePaywallView( paywall = paywall, observer = myPaywallObserver, customTags = customTags, ) ``` ## カスタムタイマー \{#custom-timers\} ペイウォールのタイマーは、期間限定の特別オファーや季節限定オファーを訴求する優れたツールです。ただし、このタイマーはオファーの有効期間やキャンペーンの期間とは連動していません。設定した値からゼロに向かってカウントダウンするだけのスタンドアロンのタイマーです。タイマーがゼロになっても何も起こりません。ゼロのまま停止するだけです。 タイマーの前後にテキストをカスタマイズして、「残り時間:10:00 秒」のようなメッセージを作成できます。 ペイウォールでカスタムタイマーを使用するには、ペイウォールビューを作成する際に渡します。 ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) AdaptyUI.createPaywallView( paywall = paywall, customTimers = customTimers ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, customTimers = customTimers, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativePaywallView( paywall = paywall, observer = myPaywallObserver, customTimers = customTimers, ) ``` --- # File: kmp-handle-paywall-actions --- --- title: "Kotlin Multiplatform SDKでボタンアクションに応答する" description: "Adaptyを使用してKotlin Multiplatformでペイウォールのボタンアクションを処理し、アプリの収益化を向上させます。" --- :::warning **購入と復元のみが自動で処理されます。** ペイウォールを閉じたりリンクを開いたりするような、それ以外のボタンアクションはすべて、アプリのコードで適切なレスポンスを実装する必要があります。 ::: Adaptyのペイウォールビルダーを使ってペイウォールを作成する場合、ボタンを適切に設定することが重要です: 1. [ペイウォールビルダーにボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、コード内でカスタムアクションと既存アクションを処理する方法を説明します。 ## AdaptyUIPaywallsEventsObserverを設定する \{#set-up-the-adaptyuipaywallsevents-observer\} ペイウォールのアクションを処理するには、`AdaptyUIPaywallsEventsObserver`インターフェースを実装し、`AdaptyUI.setPaywallsEventsObserver()`で設定する必要があります。これはアプリのライフサイクルの早い段階、通常はメインアクティビティやアプリの初期化時に行います。 ```kotlin // In your app initialization AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close**アクションを割り当てます。 2. アプリのコードで、ペイウォールを閉じる`close`アクションのハンドラーを実装します。 :::info Kotlin Multiplatform SDKでは、`CloseAction`と`AndroidSystemBackAction`がデフォルトでペイウォールを閉じます。ただし、必要に応じてコードでこの動作をオーバーライドできます。たとえば、あるペイウォールを閉じたときに別のペイウォールを開くといった使い方が可能です。 ::: ```kotlin class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { AdaptyUIAction.CloseAction, AdaptyUIAction.AndroidSystemBackAction -> view.dismiss() } } } // Set up the observer AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` [`createNativePaywallView`](kmp-present-paywalls#without-compose-multiplatform)を使用している場合、`view.dismiss()`を呼び出しても効果はありません。このビューはKMPスタックを通じて表示されるのではなく、レイアウトに埋め込まれているためです。代わりに、レイアウトからビューを削除し、`dispose()`を呼び出してください。 ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーに**Link**要素を追加し、**Open URL**アクションが設定されたボタンと同じ方法で処理してください。 ::: ペイウォールからリンクを開くボタン(例:**利用規約**や**プライバシーポリシー**)を追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL**アクションを割り当てて、開きたいURLを入力します。 2. アプリのコードで、受け取ったURLをブラウザで開く`openUrl`アクションのハンドラーを実装します。 :::info Kotlin Multiplatform SDKでは、`OpenUrlAction`が開くべきURLを提供します。確認ダイアログの表示やアプリ独自のURL処理方法を使用するなど、URL開封処理のカスタムロジックを実装できます。 ::: ```kotlin class MyAdaptyUIPaywallsEventsObserver( private val uriHandler: UriHandler ) : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.OpenUrlAction -> { // Show confirmation dialog before opening URL mainUiScope.launch { val selectedAction = view.showDialog( title = "Open URL?", content = action.url, primaryActionTitle = "Cancel", secondaryActionTitle = "Open" ).getOrNull() when (selectedAction) { AdaptyUIDialogActionType.PRIMARY -> { // User cancelled } AdaptyUIDialogActionType.SECONDARY -> { // User confirmed - open URL uriHandler.openUri(action.url) } else -> Unit } } } } } } // Set up the observer with UriHandler AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver(uriHandler)) ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、ID「login」の**Custom**アクションを割り当てます。 2. アプリのコードで、ユーザーを識別するカスタムアクションのハンドラーを実装します。 ```kotlin class MyAdaptyUIObserver : AdaptyUIObserver { override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { if (action.action == "login") { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } } } } ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom**アクションを割り当ててIDを設定します。 2. アプリのコードで、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます: ```kotlin class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { when (action.action) { "login" -> { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } } } } } // Set up the observer AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` --- # File: kmp-handling-events --- --- title: "Kotlin Multiplatform - ペイウォールイベントの処理" description: "Adaptyのイベントトラッキングツールを使って、Kotlin Multiplatformのサブスクリプションイベントを効率的に処理します。" --- [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元を行うための追加コードは不要です。ただし、アプリが対応できるいくつかのイベントが発生します。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)や、ペイウォール上で行われた購入関連のアクションに関する通知が含まれます。以下でこれらのイベントへの対応方法を説明します。 :::warning このガイドは**新しいペイウォールビルダーのペイウォール**専用です。 ::: モバイルアプリのペイウォール画面で発生するプロセスを制御・監視するには、`AdaptyUIPaywallsEventsObserver` インターフェースのメソッドを実装してください。一部のメソッドには、一般的なシナリオを自動的に処理するデフォルト実装があります。 :::note これらのメソッドは、ペイウォールイベントに応じたカスタムロジックを追加する場所です。`view.dismiss()` を使ってペイウォールを閉じることも、その他のカスタム動作を実装することもできます。 ::: ## ユーザー生成イベント \{#user-generated-events\} ### ペイウォールの表示・非表示 \{#paywall-appearance-and-disappearance\} ペイウォールが表示または非表示になると、これらのメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidAppear(view: AdaptyUIPaywallView) { // Handle paywall appearance // You can track analytics or update UI here } override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) { // Handle paywall disappearance // You can track analytics or update UI here } ``` :::note - iOS では、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップしてアプリ内ブラウザでウェブペイウォールが開いたときにも、`paywallViewDidAppear` が呼び出されます。 - iOS では、ペイウォールからアプリ内ブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも、`paywallViewDidDisappear` が呼び出されます。 :::
イベント例(クリックして展開) ```javascript // Paywall appeared { // No additional data } // Paywall disappeared { // No additional data } ```
### プロダクト選択 \{#product-selection\} ユーザーが購入するプロダクトを選択すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) { // Handle product selection // You can update UI or track analytics here } ```
イベント例(クリックして展開) ```javascript { "productId": "premium_monthly" } ```
### 購入開始 \{#started-purchase\} ユーザーが購入プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) { // Handle purchase start // You can show loading indicators or track analytics here } ```
イベント例(クリックして展開) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
### 購入成功・キャンセル・保留 \{#successful-canceled-or-pending-purchase\} 購入が成功すると、このメソッドが呼び出されます。デフォルトでは、ユーザーによってキャンセルされた場合を除き、ペイウォールを自動的に閉じます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishPurchase( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { when (purchaseResult) { is AdaptyPurchaseResult.Success -> { // Check if user has access to premium features if (purchaseResult.profile.accessLevels["premium"]?.isActive == true) { view.dismiss() } } AdaptyPurchaseResult.Pending -> { // Handle pending purchase (e.g., user will pay offline with cash) } AdaptyPurchaseResult.UserCanceled -> { // Handle user cancellation } } } ```
イベント例(クリックして展開) ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Pending" } } // User canceled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "UserCanceled" } } ```
購入が成功した場合は、ペイウォール画面を閉じることをお勧めします。 ### 購入失敗 \{#failed-purchase\} エラーにより購入が失敗すると、このメソッドが呼び出されます。これには StoreKit/Google Play Billing のエラー(支払い制限、無効なプロダクト、ネットワーク障害)、トランザクション検証の失敗、システムエラーが含まれます。なお、ユーザーによるキャンセルの場合は、キャンセル結果とともに `paywallViewDidFinishPurchase` が呼び出され、保留中の支払いではこのメソッドは呼び出されません。 ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailPurchase( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError ) { // Add your purchase failure handling logic here // For example: show error message, retry option, or custom error handling } ```
イベント例(クリックして展開) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ```
### 復元開始 \{#started-restore\} ユーザーが復元プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidStartRestore(view: AdaptyUIPaywallView) { // Handle restore start // You can show loading indicators or track analytics here } ``` ### 復元成功 \{#successful-restore\} 購入の復元が成功すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) { // Add your successful restore handling logic here // For example: show success message, update UI, or dismiss paywall // Check if user has access to premium features if (profile.accessLevels["premium"]?.isActive == true) { view.dismiss() } } ```
イベント例(クリックして展開) ```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" } ] } } ```
ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることをお勧めします。確認方法については、[サブスクリプションステータス](subscription-status)を参照してください。 ### 復元失敗 \{#failed-restore\} `Adapty.restorePurchases()` が失敗すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your restore failure handling logic here // For example: show error message, retry option, or custom error handling } ```
イベント例(クリックして展開) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
### ウェブ決済ナビゲーション完了 \{#web-payment-navigation-completion\} ユーザーが[ウェブペイウォール](web-paywall)を使って購入プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishWebPaymentNavigation( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError? ) { if (error != null) { // Handle web payment navigation error } else { // Handle successful web payment navigation } } ```
イベント例(クリックして展開) ```javascript // Successful web payment 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 web payment navigation { "product": null, "error": { "code": "web_payment_failed", "message": "Web payment navigation failed", "details": { "underlyingError": "Network connection error" } } } ```
## データ取得とレンダリング \{#data-fetching-and-rendering\} ### プロダクト読み込みエラー \{#product-loading-errors\} 初期化時にプロダクトを渡さない場合、AdaptyUI は必要なオブジェクトをサーバーから自動的に取得します。この操作が失敗した場合、AdaptyUI はこのメソッドを呼び出してエラーを報告します: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your product loading failure handling logic here // For example: show error message, retry option, or custom error handling } ```
イベント例(クリックして展開) ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ```
### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生した場合、このメソッドによって報告されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) { // Handle rendering error // In a normal situation, such errors should not occur // If you come across one, please let us know } ```
イベント例(クリックして展開) ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ```
通常の状況では、このようなエラーは発生しないはずです。もし遭遇した場合は、ぜひお知らせください。 --- # File: kmp-use-fallback-paywalls --- --- title: "Kotlin Multiplatform - フォールバックペイウォールを使用する" description: "ユーザーがオフラインの場合やAdaptyサーバーが利用できない場合に対応する" --- スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック設定ファイルをアプリケーションに追加します。 * ターゲットプラットフォームが Android の場合、フォールバック設定ファイルを `android/app/src/main/assets/` フォルダに移動します。 * ターゲットプラットフォームが iOS の場合、フォールバック JSON ファイルをプロジェクトバンドルに追加します。(**File** -> **Add Files to YourProjectName**) 2. ターゲットのペイウォールまたはオンボーディングを取得する**前に**、`.setFallback` メソッドを呼び出します。 3. ターゲットプラットフォームに応じて `assetId` パラメータを設定します。 * Android: `assets` ディレクトリからの相対ファイルパスを使用します。 * iOS: ファイル名(拡張子含む)を使用します。 ```kotlin showLineNumbers Adapty.setFallback(assetId = "fallback.json") .onSuccess { // Fallback paywalls loaded successfully } .onError { error -> // Handle the error } ``` パラメータ: | パラメータ | 説明 | | :---------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **assetId** | フォールバック設定のファイル名(iOS)。
`assets` ディレクトリからの相対パスで指定したフォールバック設定ファイルのパス(Android)。 | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: kmp-localizations-and-locale-codes --- --- title: "Kotlin Multiplatform SDKでローカライゼーションとロケールコードを使用する" description: "Kotlin Multiplatformアプリでグローバルなユーザーにリーチするために、アプリのローカライゼーションとロケールコードを管理します。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが必要になるシナリオはいくつかあります。たとえば、アプリの現在のローカライゼーションに合った正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なることがあります。そのため、Adaptyがサポートするすべてのプラットフォームで統一した内部標準を採用しています。ただし、これらのコードが複雑であるため、サーバーに送信している内容と、その後何が起こるかを正確に理解することがとても重要です。そうすることで、常に期待通りの結果を受け取ることができます。 ## Adaptyにおけるロケールコードの標準 \{#locale-code-standard-at-adapty\} ロケールコードについて、Adaptyは[BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag)を若干修正したものを使用しています。各コードは小文字のサブタグをハイフンで区切って構成されます。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} AdaptyがクライアントサイドSDKからロケールコードを含む呼び出しを受け取り、対応するペイウォールのローカライゼーションを検索する際、以下の処理が行われます: 1. 受信したロケール文字列を小文字に変換し、アンダースコア(`_`)をすべてハイフン(`-`)に置換します 2. 完全一致するロケールコードのローカライゼーションを検索します 3. 一致するものが見つからない場合、最初のハイフンより前の部分文字列(`pt-br` に対しては `pt`)を取り出して、一致するローカライゼーションを検索します 4. それでも一致するものが見つからない場合、デフォルトの `en` ローカライゼーションを返します これにより、`'pt_BR'` を送信したiOSデバイス、`pt-BR` を送信したAndroidデバイス、`pt-br` を送信した別のデバイスはすべて同じ結果を受け取ります。 ## ローカライゼーションの実装:推奨方法 \{#implementing-localizations-recommended-way\} ローカライゼーションについて検討しているなら、おそらくすでにプロジェクトでローカライズされた文字列リソースを扱っているでしょう。その場合、各リソースファイルに対応するローカライゼーション用のAdaptyロケールコードをキーと値のペアとして追加することをお勧めします。そして、次のようにSDKを呼び出す際にそのキーの値を取り出して使用してください: ```kotlin showLineNumbers // 1. Add the Adapty locale code to your Compose Multiplatform resources /* composeResources/values/strings.xml (default — English) */ en /* composeResources/values-es/strings.xml (Spanish) */ es /* composeResources/values-pt-rBR/strings.xml (Portuguese — Brazil) */ pt-br // 2. Extract and use the locale code suspend fun fetchPaywall() { val locale = getString(Res.string.adapty_paywalls_locale) Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = locale ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } } ``` この方法により、アプリのすべてのユーザーに対してどのローカライゼーションが取得されるかを完全に制御できます。 Compose Multiplatformのリソースを使用していない場合でも、同じ考え方は他のローカライゼーションライブラリ(例:[moko-resources](https://github.com/icerockdev/moko-resources))にも適用できます。各ロケールのリソースバンドルにAdaptyロケールコードを文字列として保存し、SDKを呼び出す前にそれを読み取るようにしてください。 ## ローカライゼーションの実装:別の方法 \{#implementing-localizations-the-other-way\} すべてのローカライゼーションに対してロケールコードを明示的に定義しなくても、同様の(ただし同一ではない)結果を得ることができます。その場合、デバイスから直接ロケールコードを取得することになりますが、`commonMain` に共通のロケールAPIが存在しないため、`expect`/`actual` 宣言が必要になります: ```kotlin showLineNumbers // commonMain expect fun currentLocaleTag(): String // androidMain actual fun currentLocaleTag(): String = Locale.getDefault().toLanguageTag() // iosMain actual fun currentLocaleTag(): String = NSLocale.currentLocale.localeIdentifier // commonMain — pass the locale code to Adapty suspend fun fetchPaywall() { Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = currentLocaleTag() ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } } ``` この方法はいくつかの理由から推奨しません: 1. iOSでは、ユーザーの優先言語とデバイスの地域ロケールは同一ではありません。`NSLocale.currentLocale.localeIdentifier` は地域ロケールを返しますが、これはユーザーが実際にアプリを読む言語と異なる場合があります。ローカライズされた文字列ファイルを使用するiOSアプリは、Appleの解決ロジックを使って両者を組み合わせており、上記の推奨方法ではこれが自動的に処理されます。 2. デバイスが返す値を正確に予測するのは難しく、それがAdaptyのローカライゼーションと一致するかどうかも不明です。デバイスのロケールには、Adaptyで設定していない拡張子や地域コードが含まれる場合があり、その場合SDKは最初のサブタグの一致、または最終的に `en` にフォールバックします。 それでもこの方法を使用する場合は、関連するすべてのユースケースに対応できていることを確認してください。 --- # File: kmp-web-paywalls --- --- title: "Kotlin Multiplatform SDKでウェブペイウォールを実装する" description: "ストアの手数料や審査なしで課金できるウェブペイウォールを設定します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン3.15以降をインストールしていることを確認してください。 ::: ## ウェブペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを使用している場合、SDKメソッドを使ってウェブペイウォールを処理する必要があります。`openWebPaywall` メソッドは以下を行います: 1. 特定のユーザーに表示されたペイウォールと、リダイレクト先のウェブページをAdaptyが紐付けるための一意のURLを生成します。 2. ユーザーがアプリに戻ったタイミングを検知し、短い間隔で `getProfile` を呼び出してプロファイルのアクセス権が更新されたかどうかを確認します。 これにより、決済が成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効になります。 :::note ユーザーがアプリに戻った後、プロファイルの更新を反映するためにUIを更新してください。AdaptyはプロファイルUpdateイベントを受信して処理します。 ::: ```kotlin showLineNumbers viewModelScope.launch { Adapty.openWebPaywall(product = product).onSuccess { // the web paywall was opened successfully }.onError { error -> // handle the error } } ``` :::note `openWebPaywall` メソッドには2つのバージョンがあります: 1. `openWebPaywall(product = product)` — ペイウォールをもとにURLを生成し、プロダクトのデータもURLに含めます。 2. `openWebPaywall(paywall = paywall)` — ペイウォールをもとにURLを生成しますが、プロダクトのデータはURLに含めません。Adaptyのペイウォールのプロダクトとウェブペイウォールのプロダクトが異なる場合に使用してください。 ::: ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、ウェブ購入ページがアプリ内に表示され、ユーザーはアプリを切り替えることなくトランザクションを完了できます。 これを有効にするには、`openIn` パラメーターを `AdaptyWebPresentation.IN_APP_BROWSER` に設定してください: ```kotlin showLineNumbers viewModelScope.launch { Adapty.openWebPaywall( product = product, openIn = AdaptyWebPresentation.IN_APP_BROWSER // default – EXTERNAL_BROWSER ).onSuccess { // the web paywall was opened successfully }.onError { error -> // handle the error } } ``` --- # File: kmp-troubleshoot-paywall-builder --- --- title: "Kotlin Multiplatform SDK でのペイウォールビルダーのトラブルシューティング" description: "Kotlin Multiplatform SDK でのペイウォールビルダーのトラブルシューティング" --- このガイドでは、Kotlin Multiplatform SDK で Adapty ペイウォールビルダーを使用して作成したペイウォールに関する一般的な問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `createPaywallView` メソッドがペイウォールビューの作成に失敗するか、ペイウォールにビュー設定がない。 **原因**: ペイウォールビルダーでデバイス表示が有効になっていない。 **解決策**: ペイウォールビルダーで **Show on device** トグルを有効にしてください。また、`AdaptyPaywall` オブジェクトの `hasViewConfiguration` プロパティを使用して、ペイウォールにビュー設定があるかどうかを確認することもできます。 ## ペイウォールのビュー数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールのビュー数が予想の2倍になっている。 **原因**: コード内で `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、この呼び出しによってビュー数が重複します。ペイウォールビルダーで作成したペイウォールでは、アナリティクスが自動的に記録されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `logShowPaywall` を呼び出していないことを確認してください。 --- # File: kmp-implement-paywalls-manually --- --- title: "Implement paywalls manually in Kotlin Multiplatform SDK" description: "Learn how to implement paywalls manually in your Kotlin Multiplatform app with Adapty SDK." --- ## Accept purchases If you are working with paywalls you've implemented yourself, you can delegate handling purchases to Adapty, using the `makePurchase` method. This way, we will handle all the user scenarios, and you will only need to handle the purchase results. :::important `makePurchase` works with products created in the Adapty dashboard. Make sure you configure products and ways to retrieve them in the dashboard by following the [quickstart guide](quickstart). ::: ## Observer mode If you want to implement your own purchase handling logic from scratch, but still want to benefit from the advanced analytics in Adapty, you can use the observer mode. :::important Consider the observer mode limitations [here](observer-vs-full-mode). ::: --- # File: kmp-quickstart-manual --- --- title: "Kotlin Multiplatform SDKのカスタムペイウォールで購入を有効にする" description: "Adapty SDKをKotlin Multiplatformのカスタムペイウォールに統合して、アプリ内課金を有効にします。" --- このガイドでは、カスタムペイウォールにAdaptyを統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を行います。 :::important **このガイドは、カスタムペイウォールを実装する開発者向けです。** 最も簡単に購入を有効にする方法を使いたい場合は、[Adapty ペイウォールビルダー](kmp-quickstart-paywalls)をご利用ください。ペイウォールビルダーでは、ノーコードのビジュアルエディターでペイウォールを作成でき、Adaptyがすべての購入ロジックを自動で処理します。アプリを再公開せずに異なるデザインをテストすることも可能です。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – 提供するプロダクトを定義する設定。Adaptyでは、ペイウォールがプロダクトを取得する唯一の手段です。この設計により、アプリのコードに触れることなく、プロダクト・価格・オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(例:`main`、`onboarding`、`settings`)。ダッシュボードでプレースメントにペイウォールを設定し、コード上でプレースメントIDを指定してリクエストします。これにより、A/Bテストの実施や、ユーザーごとに異なるペイウォールを表示することが簡単になります。 カスタムペイウォールを使う場合でも、これらの概念を理解しておくことが重要です。基本的には、アプリで販売するプロダクトを管理するための仕組みです。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定により、プロダクトを取得できるようになります。ダッシュボードで何をすべきかを理解するには、[こちら](quickstart)のクイックスタートガイドに従ってください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず利用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で処理します。詳細を理解し、ユーザーを正しく扱うには、[識別クイックスタートガイド](kmp-quickstart-identify)をお読みください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順を実行します。 1. `getPaywall`メソッドに[プレースメント](placements)IDを渡して`paywall`オブジェクトを取得する。 2. `getPaywallProducts`メソッドを使って、このペイウォールのプロダクト配列を取得する。 ```kotlin showLineNumbers fun loadPaywall() { Adapty.getPaywall(placementId = "YOUR_PLACEMENT_ID") .onSuccess { paywall -> Adapty.getPaywallProducts(paywall = paywall) .onSuccess { products -> // Use products to build your custom paywall UI } .onError { error -> // Handle the error } } .onError { error -> // Handle the error } } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォール内でプロダクトをタップしたら、選択したプロダクトを引数に`makePurchase`メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```kotlin showLineNumbers fun purchaseProduct(product: AdaptyPaywallProduct) { Adapty.makePurchase(product = product) .onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // Purchase successful, profile updated } is AdaptyPurchaseResult.UserCanceled -> { // User canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Purchase is pending (e.g., user will pay offline with cash) } } } .onError { error -> // Handle the error } } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる手段を提供することを求めています。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```kotlin showLineNumbers fun restorePurchases() { Adapty.restorePurchases() .onSuccess { profile -> // Restore successful, profile updated } .onError { error -> // Handle the error } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! ペイウォールをアプリに表示する準備が整いました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を完了できることを確認してください。本番環境に近い実装例については、サンプルアプリの[AppViewModel.kt](https://github.com/adaptyteam/AdaptySDK-KMP/blob/main/example/composeMultiplatformApp/composeApp/src/commonMain/kotlin/com/adapty/exampleapp/AppViewModel.kt)を参照してください。適切なエラーハンドリングと状態管理を含む購入処理の実装例が確認できます。 次に、[ユーザーが購入を完了しているかどうかを確認](kmp-check-subscription-status)し、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断します。 --- # File: fetch-paywalls-and-products-kmp --- --- title: "Kotlin Multiplatform SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Kotlin Multiplatform SDKでペイウォールとプロダクトを取得し、ユーザーの収益化を強化します。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズされたペイウォールの取得方法については、[ペイウォールビルダーのペイウォールとその設定を取得する](kmp-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 :::
モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開) 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに追加する](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに追加する](create-placement)。 4. モバイルアプリに[Adapty SDKをインストールする](sdk-installation-kotlin-multiplatform)。
## ペイウォール情報を取得する \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Playの両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合されており、特定のモバイルアプリのプレースメントで表示できます。 プロダクトを表示するには、`getPaywall`メソッドを使用していずれかの[プレースメント](placements)から[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべき唯一のIDはプレースメントIDです。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日2つのプロダクトが返され、明日3つになった場合でも、コードを変更せずにすべてを表示できるようにしてください。 ::: ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語、2番目は地域を表します。

例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。

| | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。

ただし、ユーザーが不安定なインターネット環境にいると思われる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad`を使用してキャッシュが存在する場合にキャッシュデータを返すことを検討してください。このシナリオでは、ユーザーが最新のデータを取得できない場合がありますが、インターネット接続が不安定でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。

キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動のクリーンアップ時にのみクリアされます。

Adapty SDKはペイウォールを2つのレイヤーで保存します: 上記の定期的に更新されるキャッシュと[フォールバックペイウォール](kmp-use-fallback-paywalls)。また、ペイウォールをより速く取得するためにCDNを使用し、CDNに到達できない場合のスタンドアロンフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのペイウォールを確実に取得できるように設計されています。

| | **loadTimeout** | デフォルト: 5秒 |

このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。

まれに、この操作が内部で複数のリクエストで構成されているため、`loadTimeout`で指定した時間より少し遅くタイムアウトする場合があります。

| プロダクトIDをハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクトの数、特別オファー(無料トライアルなど)は随時変更される可能性があります。コードがこれらのシナリオに対応できるようにしてください。 例えば、最初に2つのプロダクトを取得した場合、アプリはその2つを表示すべきです。後で3つのプロダクトを取得した場合、コードを変更せずに3つすべてを表示できるようにしてください。ハードコードすべき唯一のものはプレースメントIDです。 レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/)オブジェクト。 | ## プロダクトを取得する \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクト配列を取得できます: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall).onSuccess { products -> // the requested products }.onError { error -> // handle the error } ``` レスポンスパラメータ: | パラメータ | 説明 | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む[`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/)オブジェクトのプロパティにアクセスする必要があるでしょう。以下は最もよく使用されるプロパティですが、利用可能なすべてのプロパティの詳細はリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライズはデバイス自体のロケールではなく、ユーザーが選択したストアの国に基づいています。 | | **Price** | ローカライズされた価格を表示するには、`product.price.localizedString`を使用します。このローカライズはデバイスのロケール情報に基づいています。`product.price.amount`を使用して価格を数値として取得することもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには、`product.price.currencySymbol`を使用します。 | | **Subscription Period** | 期間(週、月、年など)を表示するには、`product.subscriptionDetails?.localizedSubscriptionPeriod`を使用します。このローカライズはデバイスのロケールに基づいています。プログラムでサブスクリプション期間を取得するには、`product.subscriptionDetails?.subscriptionPeriod`を使用します。そこから`unit`列挙型にアクセスして長さ(DAY、WEEK、MONTH、YEAR、またはUNKNOWN)を取得できます。`numberOfUnits`の値は期間単位の数を示します。例えば、四半期サブスクリプションの場合、unitプロパティに`MONTH`、numberOfUnitsプロパティに`3`が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれているかどうかを示すバッジやインジケーターを表示するには、`product.subscriptionDetails?.introductoryOfferPhases`プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含むことができるリストです。各フェーズオブジェクトには以下の便利なプロパティがあります:
• `paymentMode`: `FREE_TRIAL`、`PAY_AS_YOU_GO`、`PAY_UPFRONT`、`UNKNOWN`の値を持つ列挙型。無料トライアルは`FREE_TRIAL`タイプになります。
• `price`: 数値としての割引価格。無料トライアルの場合は`0`を確認してください。
• `localizedNumberOfPeriods`: デバイスのロケールを使用してローカライズされた、オファーの長さを説明する文字列。例えば、3日間のトライアルオファーの場合、このフィールドに`3 days`と表示されます。
• `subscriptionPeriod`: オファー期間の個別の詳細を取得するには、このプロパティを使用します。オファーに対しても前のセクションと同じ方法で機能します。
• `localizedSubscriptionPeriod`: ユーザーのロケール向けにフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスを高速化することを心配する必要はありません。ただし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に想定以上の時間がかかる可能性があります。そのような状況では、ペイウォールをまったく表示しないよりも、スムーズなユーザーエクスペリエンスを確保するためにデフォルトのペイウォールを表示したい場合があります。 これに対処するために、指定されたプレースメントの**All Users**オーディエンス向けペイウォールを取得する`getPaywallForDefaultAudience`メソッドを使用できます。ただし、推奨されるアプローチは上記の[ペイウォール情報を取得する](fetch-paywalls-and-products-kmp#fetch-paywall-information)セクションで詳しく説明されている`getPaywall`メソッドを使用することである点を理解することが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **潜在的な後方互換性の問題**: 異なるアプリバージョン(現在および将来)に対して異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールで問題が発生する可能性を受け入れるかのいずれかになります。 - **ターゲティングの喪失**: すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらの欠点を許容してペイウォール取得の高速化のメリットを得たい場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでなければ、[上記](fetch-paywalls-and-products-kmp#fetch-paywall-information)で説明した`getPaywall`を使用してください。 ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語、2番目は地域を表します。

例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。

| | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。

ただし、ユーザーが不安定なインターネット環境にいると思われる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad`を使用してキャッシュが存在する場合にキャッシュデータを返すことを検討してください。このシナリオでは、ユーザーが最新のデータを取得できない場合がありますが、インターネット接続が不安定でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。

キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動のクリーンアップ時にのみクリアされます。

| --- # File: present-remote-config-paywalls-kmp --- --- title: "Kotlin Multiplatform SDKでリモートコンフィグを使ったペイウォールをレンダリングする" description: "Adapty Kotlin Multiplatform SDKでリモートコンフィグペイウォールを表示し、ユーザー体験をパーソナライズする方法をご紹介します。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合は、ユーザーに表示するためのレンダリング処理をモバイルアプリのコードに実装する必要があります。リモートコンフィグはニーズに合わせた柔軟性を提供するため、何を含めるか、またペイウォールのビューをどのように表示するかはすべてあなたの判断に委ねられています。リモートコンフィグを取得するメソッドを提供しており、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String // use the remote config values }.onError { error -> // handle the error } ``` 必要な値をすべて取得したら、それらをレンダリングして視覚的に魅力的なページに組み立てましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにして、異なるデバイスでもシームレスで使いやすい体験を提供してください。 :::warning [ペイウォール表示イベントの記録](present-remote-config-paywalls-kmp#track-paywall-view-events)を必ず行ってください。これにより、Adapty アナリティクスがファネルや A/B テストの情報を収集できるようになります。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細については、[購入処理](kmp-making-purchases)をご覧ください。 [フォールバックペイウォールというバックアップペイウォールの作成](kmp-use-fallback-paywalls)をお勧めします。このバックアップは、インターネット接続がない場合やキャッシュが利用できない場合にユーザーに表示され、そのような状況でもスムーズな体験を確保します。 ## ペイウォール表示イベントを記録する \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス計測をサポートします。購入データは自動的に収集されますが、ペイウォールの表示ログはユーザーがペイウォールを見たタイミングを把握しているのはあなただけなので、手動での記録が必要です。 ペイウォール表示イベントをログに記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。すると、ファネルや A/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示する場合は、`.logShowPaywall(paywall)` の呼び出しは不要です。 ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall = paywall) .onSuccess { // paywall view logged successfully } .onError { error -> // handle the error } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------- | :------- |:-------------------------------------------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/) オブジェクト。 | --- # File: kmp-making-purchases --- --- title: "Kotlin Multiplatform SDKでモバイルアプリ内で購入を行う" description: "Adaptyを使用したアプリ内課金とサブスクリプションの処理に関するガイド。" --- モバイルアプリ内にペイウォールを表示することは、プレミアムコンテンツやサービスへのアクセスをユーザーに提供するための重要なステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入をサポートできます。 ペイウォールビルダーを使用しない場合は、購入を完了してコンテンツをアンロックするために、`.makePurchase()` という別のメソッドを使用する必要があります。このメソッドは、ユーザーがペイウォールを利用して購入処理を進めるための入り口となります。 ペイウォールに、ユーザーが購入しようとしているプロダクトに対する有効なプロモーションオファーが設定されている場合、Adaptyは購入時に自動的にそのオファーを適用します。 :::warning 初回オファーが自動的に適用されるのは、ペイウォールビルダーで設定したペイウォールを使用している場合に限ります。 それ以外の場合は、[iOS での初回オファーの適用資格を確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)必要があります。この手順を省略すると、リリース時にアプリが審査で却下される可能性があります。また、初回オファーの対象ユーザーに通常価格が請求されるリスクもあります。 ::: [初期設定](quickstart)をすべての手順を飛ばさずに完了していることを確認してください。これが完了していないと、購入を検証できません。 ## 購入を行う \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されるため、この手順はスキップできます。 **ステップごとのガイダンスをお探しですか?** エンドツーエンドの実装手順については、[クイックスタートガイド](kmp-implement-paywalls-manually)をご覧ください。 ::: ```kotlin showLineNumbers Adapty.makePurchase(product = product).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } }.onError { error -> // Handle the error } ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | | :---------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------| | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) オブジェクト。 | レスポンスパラメータ: | パラメータ | 説明 | |---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

リクエストが成功した場合、レスポンスにはこのオブジェクトが含まれます。[AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) オブジェクトは、ユーザーのアクセスレベル、サブスクリプション、アプリ内の買い切り購入に関する包括的な情報を提供します。

アクセスレベルのステータスを確認して、ユーザーが必要なアクセス権を持っているかどうかを判断してください。

| :::warning **注意:** Apple の StoreKit バージョンが v2.0 未満で、Adapty SDK バージョンが v2.9.0 未満の場合は、代わりに [Apple App Store 共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を提供する必要があります。この方法は現在 Apple により非推奨となっています。 ::: ## 購入時にサブスクリプションを変更する \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新する代わりに新しいサブスクリプションを選択した場合、その動作はアプリストアによって異なります。Google Play の場合、サブスクリプションは自動的に更新されません。以下の説明に従って、モバイルアプリのコードで切り替えを管理する必要があります。 Android でサブスクリプションを別のものに切り替えるには、追加パラメータを指定して `.makePurchase()` メソッドを呼び出してください: ```kotlin showLineNumbers val subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters( oldSubVendorProductId = "old_subscription_product_id", replacementMode = AdaptyAndroidSubscriptionUpdateReplacementMode.CHARGE_FULL_PRICE ) val purchaseParams = AdaptyPurchaseParameters.Builder() .setSubscriptionUpdateParams(subscriptionUpdateParams) .build() Adapty.makePurchase( product = product, parameters = purchaseParams ).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } }.onError { error -> // Handle the error } ``` 追加リクエストパラメータ: | パラメータ | 必須 | 説明 | |:---------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **parameters** | 任意 | [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) を通じて渡される [`AdaptyAndroidSubscriptionUpdateParameters`](https://kmp.adapty.io/////adapty/com.adapty.kmp.models/-adapty-android-subscription-update-parameters/) オブジェクト。 | サブスクリプションと切り替えモードについては、Google Developer ドキュメントで詳しく確認できます: - [切り替えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [切り替えモードに関する Google の推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 切り替えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意:このメソッドはサブスクリプションのアップグレードにのみ対応しています。ダウングレードはサポートされていません。 - 切り替えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意:実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了した時点でのみ適用されます。 ## iOS でオファーコードを利用する \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';
オファーコードについて オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。
アプリ内でコード引き換えシートを表示するには: ```kotlin showLineNumbers Adapty.presentCodeRedemptionSheet() .onSuccess { // code redemption sheet presented successfully } .onError { error -> // handle the error } ``` :::danger 確認された事例によると、一部のアプリではオファーコード引き換えシートが正常に動作しないことがあります。ユーザーを直接 App Store にリダイレクトすることをお勧めします。 そのためには、次の形式の URL を開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## プリペイドプランを管理する(Android) \{#manage-prepaid-plans-android\} アプリユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例:数か月分の非更新型サブスクリプションを購入するなど)を利用できる場合、プリペイドプランの[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にすることができます。 ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withGoogleEnablePendingPrepaidPlans(true) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } ``` --- # File: kmp-restore-purchase --- --- title: "Kotlin Multiplatform SDKでのアプリ内購入の復元" description: "シームレスなユーザー体験を確保するためにAdaptyで購入を復元する方法を学びます。" --- 購入の復元は、サブスクリプションやアプリ内課金などの以前に購入したコンテンツへのアクセスを、再度料金を請求されることなく取り戻せる機能です。この機能は、アプリをアンインストール・再インストールしたユーザーや、新しいデバイスに切り替えたユーザーが、以前に購入したコンテンツに再度料金を支払わずにアクセスしたい場合に特に便利です。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: ペイウォールのカスタマイズに[ペイウォールビルダー](adapty-paywall-builder)を使用していない場合に購入を復元するには、`.restorePurchases()`メソッドを呼び出します: ```kotlin showLineNumbers Adapty.restorePurchases().onSuccess { profile -> if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // successful access restore } }.onError { error -> // handle the error } ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

[`AdaptyProfile`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-profile/)オブジェクトです。このモデルにはアクセスレベル、サブスクリプション、および非サブスクリプション購入に関する情報が含まれています。

ユーザーがアプリにアクセスできるかどうかを判断するには、**アクセスレベルのステータス**を確認してください。

| :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-kmp --- --- title: "Kotlin Multiplatform SDK でオブザーバーモードを実装する" description: "Kotlin Multiplatform SDK において、Adapty のオブザーバーモードを実装してユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラを持っており、Adapty への完全移行をまだ検討していない場合は、[オブザーバーモード](observer-vs-full-mode)を試してみてください。基本的な使い方では、オブザーバーモードは高度な分析機能とアトリビューション・アナリティクスシステムとのシームレスな連携を提供します。 このモードで問題なければ、以下の手順だけで利用できます: 1. Adapty SDK を設定する際に `observerMode` パラメータを `true` に設定してオブザーバーモードをオンにします。設定手順は [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) を参照してください。 2. 既存の購入インフラからのトランザクションを [Adapty に報告](report-transactions-observer-mode-kmp)します。 ## オブザーバーモードの設定 \{#observer-mode-setup\} 購入処理とサブスクリプションステータスの管理を自分で行い、サブスクリプションイベントの送信と分析に Adapty を使用する場合は、オブザーバーモードをオンにしてください。 :::important オブザーバーモードで動作している場合、Adapty SDK はトランザクションをクローズしません。そのため、トランザクションの処理は必ずご自身で行ってください。 ::: ```kotlin showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withObserverMode(true) // default false .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised in observer mode") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [オブザーバーモード](observer-vs-full-mode)を制御する真偽値です。デフォルト値は `false` です。 | ## オブザーバーモードで Adapty のペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adapty のペイウォールや A/B テスト機能も併用したい場合は可能ですが、オブザーバーモードでは追加の設定が必要です。上記の手順に加えて、以下を行ってください: 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-kmp)の場合と同様に、通常通りペイウォールを表示します。 3. 購入トランザクションに[ペイウォールを紐付け](report-transactions-observer-mode-kmp)ます。 --- # File: report-transactions-observer-mode-kmp --- --- title: "Kotlin Multiplatform SDKのObserverモードでトランザクションを報告する" description: "Kotlin Multiplatform SDKのAdapty ObserverモードでユーザーインサイトとRevenue追跡のための購入トランザクションを報告します。" --- Observerモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動的に追跡することができません。アプリストアからのトランザクションを手動で報告する必要があります。アナリティクスのエラーを防ぐために、アプリをリリースする**前**にこの設定を完了することが重要です。 `reportTransaction`を使用して、各トランザクションをAdaptyに明示的に報告してください。 :::warning **トランザクションの報告を省略しないでください!** `reportTransaction`を呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`variationId`を含めてください。これにより、購入がトリガーしたペイウォールに関連付けられ、正確なペイウォールアナリティクスが確保されます。 ```kotlin showLineNumbers Adapty.reportTransaction( transactionId = "your_transaction_id", variationId = paywall.variationId ).onSuccess { profile -> // Transaction reported successfully // profile contains updated user data }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | --------------- | --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | 必須 | アプリストアの購入から取得したトランザクションID。通常、ストアから返される購入トークンまたはトランザクション識別子です。 | | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | --- # File: kmp-troubleshoot-purchases --- --- title: "Kotlin Multiplatform SDKの購入に関するトラブルシューティング" description: "Kotlin Multiplatform SDKの購入に関するトラブルシューティング" --- このガイドでは、Kotlin Multiplatform SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseは正常に呼び出されるが、プロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase`メソッドが正常に完了するにもかかわらず、ユーザーのプロファイルとサブスクリプションの状態がAdaptyに反映されない。 **原因**: 通常、これはGoogle Play Storeのセットアップが不完全か、設定に問題があることを示しています。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して`makePurchase`メソッドが複数回呼び出されている。 **原因**: UIの状態管理の問題や、ユーザーの素早い操作によって購入フローが複数回トリガーされる場合に発生します。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyerror-cantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで`makePurchase`を使用すると`AdaptyError.cantMakePayments`が発生する。 **原因**: オブザーバーモードでは、Adaptyの`makePurchase`メソッドを使用せず、購入処理を自前で行う必要があります。 **解決策**: 購入に`makePurchase`を使用している場合は、オブザーバーモードを無効にしてください。`makePurchase`を使用するか、オブザーバーモードで自前の購入処理を行うか、どちらか一方を選択する必要があります。詳細は[オブザーバーモードの実装](implement-observer-mode-kmp)を参照してください。 ## Adaptyエラー: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **問題**: Google Play Storeから課金不可のエラーが返される。 **原因**: このエラーはAdatyとは無関係です。デバイスで課金が利用できないことを示すGoogle Play Billing Libraryのエラーです。 **解決策**: このエラーはAdaptyとは無関係です。Play Storeのドキュメントで詳細を確認できます: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers`が見つからないというエラーが発生する。 **原因**: 通常、これはサンドボックステストに関連する問題です。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。これにより、サンドボックス環境での購入完了ハンドラーの問題が解決することが多いです。 --- # File: kmp-user --- --- title: "Users & access in Kotlin Multiplatform SDK" description: "Learn how to work with users and access levels in your Kotlin Multiplatform app with Adapty SDK." --- This page contains all guides for working with users and access levels in your Kotlin Multiplatform app. Choose the topic you need: - **[Identify users](kmp-identifying-users)** - Learn how to identify users in your app - **[Update user data](kmp-setting-user-attributes)** - Set user attributes and profile data - **[Listen for subscription status changes](kmp-listen-subscription-changes)** - Monitor subscription changes in real-time - **[Kids Mode](kids-mode-kmp)** - Implement Kids Mode for your app --- # File: kmp-identifying-users --- --- title: "Kotlin Multiplatform SDK でユーザーを識別する" description: "Adapty でユーザーを識別して、パーソナライズされたサブスクリプション体験を向上させましょう。" --- Adapty はすべてのユーザーに対して内部プロファイル ID を作成します。ただし、独自の認証システムを持っている場合は、独自の Customer User ID を設定する必要があります。[Profiles](profiles-crm) セクションで Customer User ID によってユーザーを検索したり、すべてのインテグレーションに送信される[サーバーサイド API](getting-started-with-server-side-api) で使用することができます。 ### 設定時に Customer User ID を設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザー ID がある場合は、`.activate()` メソッドの `customerUserId` パラメータとして渡すだけです: ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("YOUR_USER_ID") .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } } ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後に Customer User ID を設定する \{#setting-customer-user-id-after-configuration\} SDK の設定時にユーザー ID がない場合は、後から `.identify()` メソッドを使っていつでも設定できます。このメソッドが最もよく使われるのは、登録後やログイン後に匿名ユーザーから認証済みユーザーへ切り替わるタイミングです。 ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID").onSuccess { // successful identify }.onError { error -> // handle the error } ``` リクエストパラメータ: - **Customer User ID**(必須): 文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーが再度アカウントにログインする場合など、Adapty のサーバーにすでにそのユーザーの情報が存在していることがあります。このような場合、Adapty SDK は自動的に新しいユーザーとして動作を切り替えます。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに対してデータを渡していた場合は、識別されたユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得する必要があることにも注意してください。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()` メソッドを呼び出すことで、いつでもユーザーをログアウトさせることができます: ```kotlin showLineNumbers Adapty.logout().onSuccess { // successful logout }.onError { error -> // handle the error } ``` その後、`.identify()` メソッドを使ってユーザーをログインさせることができます。 ## `appAccountToken` を割り当てる(iOS) \{#assign-appaccounttoken-ios\} [`iosAppAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) は、App Store のトランザクションを内部ユーザー ID に紐付けるための **UUID** です。 StoreKit はすべてのトランザクションにこのトークンを関連付けるため、バックエンドで App Store のデータをユーザーと照合することができます。 ユーザーごとに安定した UUID を生成し、同じアカウントに対してデバイスをまたいで再利用してください。 これにより、購入や App Store の通知が正しく紐付けられたままになります。 トークンは、SDK のアクティベーション時またはユーザーの識別時の 2 つの方法で設定できます。 :::important `iosAppAccountToken` は必ず `customerUserId` と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: ```kotlin showLineNumbers // During configuration: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } // Or when identifying users Adapty.identify( customerUserId = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ).onSuccess { // successful identify }.onError { error -> // handle the error } ``` ## 難読化アカウント ID を設定する(Android) \{#set-obfuscated-account-ids-android\} Google Play では、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化アカウント ID が必要です。これらの ID は、ユーザー情報を匿名に保ちながら Google Play が購入を識別するのに役立ち、不正防止やアナリティクスにおいて特に重要です。 アプリが機密性の高いユーザーデータを扱っている場合や、特定のプライバシー規制への準拠が求められる場合に、これらの ID を設定する必要があるかもしれません。難読化 ID により、Google Play は実際のユーザー識別子を公開せずに購入を追跡できます。 :::important `androidObfuscatedAccountId` は必ず `customerUserId` と一緒に渡す必要があります。 難読化アカウント ID のみを渡した場合、トランザクションに含まれません。 ::: ```kotlin showLineNumbers // During configuration: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } // Or when identifying users Adapty.identify( customerUserId = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ).onSuccess { // successful identify }.onError { error -> // handle the error } ``` ## デバイスをまたいでユーザーを検出する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: kmp-setting-user-attributes --- --- title: "Kotlin Multiplatform SDKでユーザー属性を設定する" description: "Adaptyでユーザー属性を設定して、オーディエンスのセグメンテーションを改善する方法を学びます。" --- メールアドレスや電話番号など、アプリのユーザーにオプションの属性を設定できます。設定した属性は、ユーザー[セグメント](segments)の作成やCRMでの確認に活用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.FEMALE) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) .onSuccess { // profile updated successfully } .onError { error -> // handle the error } ``` `updateProfile` メソッドで以前に設定した属性はリセットされません。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` で使用できるキー `` と値 `` は以下のとおりです。 | キー | 値 | |---|-----| |

email

phoneNumber

firstName

lastName

| String | | gender | Enum(使用可能な値: `AdaptyProfile.Gender.FEMALE`、`AdaptyProfile.Gender.MALE`、`AdaptyProfile.Gender.OTHER`) | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定できます。これらは通常、アプリの使用状況に関連するものです。たとえば、フィットネスアプリであれば週あたりのエクササイズ回数、語学学習アプリであればユーザーの習熟度レベルなどが考えられます。セグメントで使用してターゲットを絞ったペイウォールやオファーを作成したり、アナリティクスでどのプロダクト指標が収益に最も影響するかを分析したりするのに役立ちます。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withCustomAttribute("key1", "value1") ``` 既存のキーを削除するには、`.withRemovedCustomAttribute()` メソッドを使用します。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withRemovedCustomAttribute("key2") ``` 設定済みのカスタム属性を事前に確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning `customAttributes` の値は最新の状態でない場合があります。ユーザー属性は複数のデバイスからいつでも送信される可能性があるため、最後の同期以降にサーバー上の属性が変更されている場合があります。 ::: ### 制限事項 \{#limits\} - ユーザーあたり最大30件のカスタム属性 - キー名は最大30文字。キー名には英数字および以下の記号が使用できます: `_` `-` `.` - 値は文字列または小数で、50文字以内。 --- # File: kmp-listen-subscription-changes --- --- title: "Kotlin Multiplatform SDKでサブスクリプションのステータスを確認する" description: "Kotlin MultiplatorformアプリでAdaptyを使用してユーザーのサブスクリプションステータスを追跡・管理し、顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションのステータス管理が簡単になります。プロダクトIDをコードに手動で埋め込む必要はありません。代わりに、[アクセスレベル](access-level)がアクティブかどうかを確認するだけで、ユーザーのサブスクリプションステータスをすぐに把握できます。 サブスクリプションステータスの確認を始める前に、[リアルタイム デベロッパー通知 (RTDN)](enable-real-time-developer-notifications-rtdn) を設定してください。 ## アクセスレベルとAdaptyProfileオブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) オブジェクトのプロパティです。アプリ起動時(例:[ユーザーを識別する](android-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があれば随時更新することを推奨します。こうすることで、都度リクエストを送らずにプロファイルオブジェクトを活用できます。 プロファイルの更新通知を受け取るには、以下の[サブスクリプションステータスを含むプロファイル更新の監視](android-listen-subscription-changes)セクションで説明しているプロファイル変更のリスナーを設定してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()` メソッドを使用してください: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> // check the access }.onError { error -> // handle the error } ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profile |

[AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) オブジェクトです。通常、ユーザーがアプリのプレミアム機能にアクセスできるかどうかを判断するには、プロファイルのアクセスレベルのステータスを確認するだけで十分です。

`.getProfile` メソッドは常にAPIへのクエリを試みるため、最新の結果を返します。ネットワーク接続がないなどの理由でAdapty SDKがサーバーから情報を取得できない場合は、キャッシュのデータが返されます。また、Adapty SDKは `AdaptyProfile` のキャッシュを定期的に更新し、情報をできるだけ最新の状態に保ちます。

| `.getProfile()` メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリには複数のアクセスレベルを設定することも可能です。たとえばニュースアプリでトピックごとにサブスクリプションを販売する場合、「sports」や「science」といったアクセスレベルを作成できます。ただし、ほとんどのケースでは1つのアクセスレベルで十分です。その場合はデフォルトの「premium」アクセスレベルをそのままご利用ください。 デフォルトの「premium」アクセスレベルを確認する例: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } }.onError { error -> // handle the error } ``` ### サブスクリプションステータスの更新を監視する \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adaptyはイベントを発火します。 Adaptyからのメッセージを受け取るには、追加の設定が必要です: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` Adaptyはアプリ起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されたキャッシュには、プロファイルのサブスクリプションステータスが保存されます。つまり、サーバーが利用できない場合でも、キャッシュされたデータからプロファイルのサブスクリプション情報を取得できます。 ただし、キャッシュから直接データをリクエストすることはできません。SDKは1分ごとにサーバーへ定期的なクエリを行い、プロファイルに関する更新や変更を確認します。新しいトランザクションやその他の更新など、変更が検出された場合は、サーバーとの同期を保つためにキャッシュデータへ反映されます。 --- # File: kmp-deal-with-att --- --- title: "Kotlin Multiplatform SDKでATTを処理する" description: "Kotlin MultiplatformでAdaptyを使い始めて、サブスクリプションのセットアップと管理を効率化しましょう。" --- アプリがAppTrackingTransparencyフレームワークを使用してアプリトラッキングの認証リクエストをユーザーに表示する場合、[認証ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)をAdaptyに送信する必要があります。 ```kotlin showLineNumbers val profileParameters = AdaptyProfileParameters.Builder() .withAttStatus(3) // 3 = ATTrackingManagerAuthorizationStatusAuthorized .build() Adapty.updateProfile(profileParameters) .onSuccess { // ATT status updated successfully } .onError { error -> // handle AdaptyError } ``` :::warning この値は変更されたらできるだけ早く送信することを強くお勧めします。そうすることで、設定済みのインテグレーションにタイムリーにデータが送信されます。 ::: --- # File: kids-mode-kmp --- --- title: "Kotlin Multiplatform SDKのキッズモード" description: "キッズモードを簡単に有効化してGoogleのポリシーに準拠。Kotlin Multiplatform SDKではGAIDや広告データを収集しません。" --- Kotlin Multiplatformアプリが子ども向けの場合、[Google](https://support.google.com/googleplay/android-developer/answer/9893335)のポリシーに従う必要があります。Adapty SDKを使用している場合、いくつかの簡単な手順でこれらのポリシーに準拠し、アプリストアの審査を通過できるよう設定できます。 ## 必要な対応 \{#whats-required\} Adapty SDKで以下の収集を無効にする必要があります: - [IDFA(広告識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android Advertising ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IPアドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザーIDの扱いにも注意が必要です。``形式のユーザーIDやメールアドレスの使用は、個人情報の収集とみなされます。キッズモードでは、ランダム化または匿名化された識別子(ハッシュ化されたIDやデバイス生成のUUIDなど)を使用することがベストプラクティスです。 ## キッズモードの有効化 \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードでIPアドレスの収集を無効にする必要があります。[App settings](https://app.adapty.io/settings/general)に移動し、**Collect users' IP address**の下にある**Disable IP address collection**をクリックしてください。 ### モバイルアプリコードの変更 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するため、Adapty SDKの初期化時にAndroid Advertising ID(AAID/GAID)とIPアドレスの収集を無効にする必要があります: ```kotlin showLineNumbers override fun onCreate() { super.onCreate() val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") // highlight-start .withGoogleAdvertisingIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised with privacy settings") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } } ``` --- # File: kmp-onboardings --- --- title: "Onboardings in Kotlin Multiplatform SDK" description: "Learn how to work with onboardings in your Kotlin Multiplatform app with Adapty SDK." --- --- # File: kmp-get-onboardings --- --- title: "Kotlin Multiplatform SDKでオンボーディングを取得する" description: "Kotlin Multiplatform向けのAdaptyでオンボーディングを取得する方法を学びます。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアル部分を設計](design-onboarding)した後、Kotlin Multiplatformアプリに表示できます。このプロセスの最初のステップは、プレースメントに関連付けられたオンボーディングとそのビュー設定を取得することです(以下で説明します)。 始める前に、以下を確認してください: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform)バージョン3.15.0以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ## オンボーディングの取得 \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得して表示する必要のある設定コンテナとして保存されます。このコンテナは、表示されるコンテンツ、表示方法、ユーザーの操作(クイズの回答やフォーム入力など)の処理方法など、エクスペリエンス全体を管理します。また、コンテナは分析イベントを自動的に追跡するため、個別にビュー追跡を実装する必要はありません。 最高のパフォーマンスを得るため、ユーザーに表示する前に画像をダウンロードする十分な時間を確保できるよう、早めにオンボーディング設定を取得してください。 オンボーディングを取得するには、`getOnboarding`メソッドを使用します: ```kotlin showLineNumbers Adapty.getOnboarding( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

| オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成された言語コードであることが求められます。最初のサブタグは言語、2つ目はリージョンを表します。

例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。

| | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` |

デフォルトでは、SDKはサーバーからデータの読み込みを試み、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。

ただし、ユーザーがインターネット接続が不安定な状況にある場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新データを取得できないことがありますが、インターネット接続が不安定な状況でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。

キャッシュはアプリを再起動しても保持され、アプリを再インストールするか手動でクリーンアップした場合にのみクリアされます。

Adapty SDKはオンボーディングをローカルに2つのレイヤーで保存します:上記の定期更新されるキャッシュとフォールバックオンボーディングです。また、オンボーディングをより高速に取得するためにCDNを使用し、CDNが利用できない場合に備えてスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを取得できるように設計されています。

| | **loadTimeout** | デフォルト: 5秒 |

このメソッドのタイムアウトを制限する値。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。

まれに、操作が内部で複数のリクエストで構成される場合があるため、このメソッドは`loadTimeout`で指定した時間よりわずかに遅れてタイムアウトする場合があります。

| レスポンスパラメーター: | パラメーター | 説明 | |:----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | オンボーディング識別子と設定、リモートコンフィグ、およびその他のプロパティを含む[`AdaptyOnboarding`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-onboarding/)オブジェクト。 | ## デフォルトオーディエンスのオンボーディングで取得を高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ瞬時に取得されるため、このプロセスの高速化について心配する必要はありません。ただし、多数のオーディエンスとオンボーディングがあり、ユーザーのインターネット接続が不安定な場合、オンボーディングの取得に想定より時間がかかることがあります。そのような状況では、オンボーディングをまったく表示しないよりも、スムーズなユーザーエクスペリエンスを確保するためにデフォルトのオンボーディングを表示したい場合があります。 これに対処するために、`getOnboardingForDefaultAudience`メソッドを使用できます。このメソッドは、**すべてのユーザー**オーディエンス向けに指定されたプレースメントのオンボーディングを取得します。ただし、推奨されるアプローチは、上記の[オンボーディングの取得](#fetch-onboarding)セクションで説明した`getOnboarding`メソッドを使用することであることを理解することが重要です。 :::warning `getOnboardingForDefaultAudience`の代わりに`getOnboarding`の使用を検討してください。前者には重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする場合に問題が発生する可能性があり、下位互換性のあるデザインが必要になるか、古いバージョンが正しく表示されないことを受け入れる必要があります。 - **パーソナライズなし**:「すべてのユーザー」オーディエンス向けのコンテンツのみを表示し、国、アトリビューション、またはカスタム属性に基づくターゲティングが行われません。 ユースケースで高速な取得がこれらのデメリットを上回る場合は、以下に示すように`getOnboardingForDefaultAudience`を使用してください。そうでない場合は、[上記](#fetch-onboarding)で説明した`getOnboarding`を使用してください。 ::: ```kotlin showLineNumbers Adapty.getOnboardingForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

| オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成された言語コードであることが求められます。最初のサブタグは言語、2つ目はリージョンを表します。
例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。 | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` |

デフォルトでは、SDKはサーバーからデータの読み込みを試み、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。

ただし、ユーザーがインターネット接続が不安定な状況にある場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新データを取得できないことがありますが、インターネット接続が不安定な状況でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。

キャッシュはアプリを再起動しても保持され、アプリを再インストールするか手動でクリーンアップした場合にのみクリアされます。

Adapty SDKはオンボーディングをローカルに2つのレイヤーで保存します:上記の定期更新されるキャッシュとフォールバックオンボーディングです。また、オンボーディングをより高速に取得するためにCDNを使用し、CDNが利用できない場合に備えてスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを取得できるように設計されています。

| --- # File: kmp-present-onboardings --- --- title: "Kotlin Multiplatform SDKでオンボーディングを表示する" description: "コンバージョンを高めるためにオンボーディングを効果的に表示する方法を学びましょう。" --- ビルダーを使ってオンボーディングをカスタマイズした場合、Kotlin Multiplatformアプリのコードでレンダリング処理を記述しなくても、ユーザーに表示できます。このようなオンボーディングには、表示内容と表示方法の両方が含まれています。 始める前に、以下を確認してください: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.16.1以降がインストールされていること。 2. [オンボーディングを作成](create-onboarding)していること。 3. オンボーディングを[プレースメント](placements)に追加していること。 Adapty Kotlin Multiplatform SDKでは、オンボーディングを表示する方法が2つあります: - **Compose Multiplatformを使用する** - **Compose Multiplatformを使用しない** ## Compose Multiplatformを使用する \{#with-compose-multiplatform\} オンボーディングを表示するには、`createOnboardingView`メソッドで作成した`view`に対して`view.present()`メソッドを呼び出します。各`view`は一度しか使用できません。再度オンボーディングを表示する必要がある場合は、`createOnboardingView`をもう一度呼び出して新しい`view`インスタンスを作成してください。 :::warning `view`を再作成せずに再利用すると、エラーが発生する場合があります。 ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createOnboardingView(onboarding = onboarding).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### iOSの表示スタイルを設定する \{#configure-ios-presentation-style\} `present()`メソッドに`iosPresentationStyle`パラメータを渡すことで、iOSでのオンボーディングの表示方法を設定できます。パラメータには`AdaptyUIIOSPresentationStyle.FULLSCREEN`(デフォルト)または`AdaptyUIIOSPresentationStyle.PAGESHEET`を指定できます。 ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createOnboardingView(onboarding = onboarding).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ### オンボーディング内のリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開きます。これにより、アプリを切り替えることなくウェブページをアプリ内で表示でき、シームレスなユーザー体験を提供します。 代わりに外部ブラウザでリンクを開きたい場合は、`externalUrlsPresentation`パラメータを`AdaptyWebPresentation.EXTERNAL_BROWSER`に設定することでこの動作をカスタマイズできます: ```kotlin showLineNumbers viewModelScope.launch { AdaptyUI.createOnboardingView( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.EXTERNAL_BROWSER // default – IN_APP_BROWSER ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ## Compose Multiplatformを使用しない \{#without-compose-multiplatform\} :::note `createNativeOnboardingView`はコアモジュール`io.adapty:adapty-kmp`の一部です。プロジェクトでCompose Multiplatformを使用しない場合、`io.adapty:adapty-kmp-ui`の依存関係は不要です。 ::: Compose Multiplatformを使わずにオンボーディングを埋め込むには、`createNativeOnboardingView`を呼び出します。レイアウトに追加できる`AdaptyNativeOnboardingView`が返されます: ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativeOnboardingView( context = context, viewModelStoreOwner = activity, onboarding = onboarding, observer = myOnboardingObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` KMPのインターフェースデフォルトメソッドはSwiftでは`@required`になるため、SwiftからSwiftから`AdaptyUIOnboardingsEventsObserver`を直接実装することはできません。まず`iosMain`でオープンな基底クラスを宣言してください: ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BaseOnboardingObserver : AdaptyUIOnboardingsEventsObserver ``` 次にSwiftでサブクラス化し、必要なメソッドのみオーバーライドします: ```swift showLineNumbers title="Swift" class MyOnboardingObserver: BaseOnboardingObserver { override func onboardingViewOnCloseAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // remove nativeView from your view hierarchy } } let nativeView = AdaptyUI.shared.createNativeOnboardingView( onboarding: onboarding, observer: MyOnboardingObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` ### ビューを破棄する \{#dispose-the-view\} レイアウトからビューを削除する際は`dispose()`を呼び出してください。これによりイベントリスナーの登録が解除され、内部リソースが解放されます。 ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` --- # File: kmp-handling-onboarding-events --- --- title: "Kotlin Multiplatform SDKでオンボーディングイベントを処理する" description: "Adaptyを使用してKotlin Multiplatformでオンボーディング関連のイベントを処理する方法。" --- 始める前に、以下を確認してください: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.15.0以降をインストール済みであること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ビルダーで設定されたオンボーディングは、アプリが応答できるイベントを生成します。これらのイベントへの対応方法について、以下で説明します。 ## オンボーディングイベントオブザーバーの設定 \{#set-up-the-onboarding-event-observer\} オンボーディングイベントを処理するには、`AdaptyUIOnboardingsEventsObserver`インターフェースを実装し、`AdaptyUI.setOnboardingsEventsObserver()`でセットアップする必要があります。これはアプリのライフサイクルの早い段階、通常はメインアクティビティやアプリの初期化時に行ってください。 ```kotlin // In your app initialization AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` ## カスタムアクション \{#custom-actions\} ビルダーでは、ボタンに**カスタム**アクションを追加してIDを割り当てることができます。このIDをコード内で使用して、カスタムアクションとして処理できます。 たとえば、ユーザーが**ログイン**や**通知を許可**といったカスタムボタンをタップすると、デリゲートメソッド`onCustomAction`がビルダーで設定したアクションIDとともに呼び出されます。「allowNotifications」のような独自のIDを作成できます。 ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnCustomAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { when (actionId) { "openPaywall" -> { // Display paywall from onboarding // You would typically fetch and present a new paywall here mainUiScope.launch { // Example: Get paywall by placement ID // val paywallResult = Adapty.getPaywall("your_placement_id") // paywallResult.onSuccess { paywall -> // val paywallViewResult = AdaptyUI.createPaywallView(paywall) // paywallViewResult.onSuccess { paywallView -> // paywallView.present() // } // } } } "allowNotifications" -> { // Handle notification permissions } else -> { // Handle other custom actions } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ```
イベントの例(クリックして展開) ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ```
## オンボーディングを閉じる \{#closing-onboarding\} オンボーディングは、ユーザーが**閉じる**アクションが割り当てられたボタンをタップすると閉じたとみなされます。ユーザーがオンボーディングを閉じたときの動作を管理する必要があります。例: :::important ユーザーがオンボーディングを閉じたときの動作を管理する必要があります。たとえば、オンボーディング自体の表示を停止する必要があります。 ::: [`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform)を使用している場合、`view.isStandaloneView`が`false`のとき、デフォルトの実装では`view.dismiss()`は呼び出されません。このコールバック内でビューをレイアウトから削除し、`dispose()`を呼び出してください。 ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnCloseAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // Dismiss the onboarding screen mainUiScope.launch { view.dismiss() } // Additional cleanup or navigation logic can be added here // For example, navigate back or show main app content } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ```
イベントの例(クリックして展開) ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
## ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディングの中でペイウォールを開きたい場合は、このイベントを処理してください。閉じた後にペイウォールを開きたい場合は、[`onboardingViewOnCloseAction`](#closing-onboarding)を処理してイベントデータに依存せずにペイウォールを開く方が、よりシンプルな方法です。 ::: オンボーディング内でペイウォールを最もシームレスに扱う方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。これにより、プレースメントIDを使ってすぐにペイウォールを取得して開くことができます: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnPaywallAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // Get the paywall using the placement ID from the action mainUiScope.launch { val paywallResult = Adapty.getPaywall(placementId = actionId) paywallResult.onSuccess { paywall -> val paywallViewResult = AdaptyUI.createPaywallView(paywall) paywallViewResult.onSuccess { paywallView -> paywallView.present() }.onError { error -> // handle the error } }.onError { error -> // handle the error } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ```
イベントの例(クリックして展開) ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ```
## オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このメソッドが呼び出されます: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewDidFinishLoading( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta ) { // Handle loading completion // You can add any initialization logic here } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ```
イベントの例(クリックして展開) ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ```
## ナビゲーションイベント \{#navigation-events\} `onboardingViewOnAnalyticsEvent`メソッドは、オンボーディングフロー中にさまざまなアナリティクスイベントが発生したときに呼び出されます。 `event`オブジェクトは以下のいずれかの型になります: | 型 | 説明 | |------------|-------------| | `AdaptyOnboardingsAnalyticsEventOnboardingStarted` | オンボーディングが読み込まれたとき | | `AdaptyOnboardingsAnalyticsEventScreenPresented` | 任意の画面が表示されたとき | | `AdaptyOnboardingsAnalyticsEventScreenCompleted` | 画面が完了したとき。省略可能な`elementId`(完了した要素の識別子)と省略可能な`reply`(ユーザーからの回答)を含む。ユーザーが画面を離れるアクションを実行したときにトリガーされる。 | | `AdaptyOnboardingsAnalyticsEventSecondScreenPresented` | 2番目の画面が表示されたとき | | `AdaptyOnboardingsAnalyticsEventUserEmailCollected` | 入力フィールドでユーザーのメールアドレスが収集されたときにトリガーされる | | `AdaptyOnboardingsAnalyticsEventOnboardingCompleted` | ユーザーが`final` IDを持つ画面に到達したときにトリガーされる。このイベントが必要な場合は、最後の画面に`final` IDを割り当てる。 | | `AdaptyOnboardingsAnalyticsEventUnknown` | 認識されないイベントタイプの場合。`name`(不明なイベントの名前)と`meta`(追加のメタデータ)を含む。 | 各イベントには以下の`meta`情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内の現在の画面の位置 | | `screensTotal` | フロー内の画面の総数 | アナリティクスイベントをトラッキングに使用する例: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnAnalyticsEvent( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, event: AdaptyOnboardingsAnalyticsEvent ) { when (event) { is AdaptyOnboardingsAnalyticsEventOnboardingStarted -> { // Track onboarding start trackEvent("onboarding_started", event.meta) } is AdaptyOnboardingsAnalyticsEventScreenPresented -> { // Track screen presentation trackEvent("screen_presented", event.meta) } is AdaptyOnboardingsAnalyticsEventScreenCompleted -> { // Track screen completion with user response trackEvent("screen_completed", event.meta, event.elementId, event.reply) } is AdaptyOnboardingsAnalyticsEventOnboardingCompleted -> { // Track successful onboarding completion trackEvent("onboarding_completed", event.meta) } is AdaptyOnboardingsAnalyticsEventUnknown -> { // Handle unknown events trackEvent(event.name, event.meta) } // Handle other cases as needed } } private fun trackEvent(eventName: String, meta: AdaptyUIOnboardingMeta, elementId: String? = null, reply: String? = null) { // Implement your analytics tracking here // For example, send to your analytics service } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ```
イベントの例(クリックして展開) ```javascript // OnboardingStarted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "welcome_screen", "screenIndex": 0, "screensTotal": 4 } } // ScreenPresented { "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 4 } } // ScreenCompleted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 }, "elementId": "profile_form", "reply": "success" } // SecondScreenPresented { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 } } // UserEmailCollected { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 } } // OnboardingCompleted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "final_screen", "screenIndex": 3, "screensTotal": 4 } } ```
--- # File: kmp-onboarding-input --- --- title: "Kotlin Multiplatform SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使用してKotlin MultiplatformアプリでオンボーディングのデータをKotlin Multiplatformで保存・活用する方法。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onboardingViewOnStateUpdatedAction` メソッドが呼び出されます。コード内でフィールドの種類を保存したり処理したりすることができます。 例: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Store user preferences or responses when (params) { is AdaptyOnboardingsSelectParams -> { // Handle single selection val id = params.id val value = params.value val label = params.label AppLogger.d("Selected option: $label (id: $id, value: $value)") } is AdaptyOnboardingsMultiSelectParams -> { // Handle multiple selections } is AdaptyOnboardingsInputParams -> { // Handle text input } is AdaptyOnboardingsDatePickerParams -> { // Handle date selection } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ```
保存されたデータの例(実装によってフォーマットが異なる場合があります) ```javascript // Example of a saved select action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "preferences_screen", "screen_index": 1, "total_screens": 3 }, "action": { "element_id": "preference_selector", "element_type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 3 }, "action": { "element_id": "interests_selector", "element_type": "multi_select", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 0, "total_screens": 3 }, "action": { "element_id": "name_input", "element_type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 0, "total_screens": 3 }, "action": { "element_id": "birthday_picker", "element_type": "date_picker", "value": { "day": 15, "month": 6, "year": 1990 } } } ```
## ユースケース \{#use-cases\} ### 入力データでユーザープロファイルを充実させる \{#enrich-user-profiles-with-data\} 入力データをユーザープロファイルにすぐに紐付けて、同じ情報を二度聞かないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](kmp-setting-user-attributes)する必要があります。 例えば、`name` というIDのテキストフィールドにユーザーの名前を入力させ、そのフィールドの値をユーザーの名前(ファーストネーム)として設定したい場合や、`email` フィールドにメールアドレスを入力させたい場合、アプリのコードは次のようになります: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Store user preferences or responses when (params) { is AdaptyOnboardingsInputParams -> { // Handle text input val builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field when (elementId) { "name" -> { when (val input = params.input) { is AdaptyOnboardingsTextInput -> { builder.withFirstName(input.value) } } } "email" -> { when (val input = params.input) { is AdaptyOnboardingsEmailInput -> { builder.withEmail(input.value) } } } } // Update profile asynchronously mainUiScope.launch { val profileParams = builder.build() val result = Adapty.updateProfile(profileParams) result.onSuccess { profile -> // Profile updated successfully AppLogger.d("Profile updated: ${profile.email}") }.onError { error -> // Handle the error AppLogger.e("Failed to update profile: ${error.message}") } } } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、オンボーディング完了後にユーザーへ表示するペイウォールをカスタマイズすることもできます。 例えば、スポーツの経験についてユーザーに質問し、ユーザーグループによって異なるCTAやプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、各選択肢に意味のあるIDを割り当てます。 2. クイズの回答をIDに基づいて処理し、ユーザーに[カスタム属性を設定](kmp-setting-user-attributes)します。 ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Handle quiz responses and set custom attributes when (params) { is AdaptyOnboardingsSelectParams -> { // Handle quiz selection val builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes when (elementId) { "experience" -> { // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.withCustomAttribute("experience", params.value) } } // Update profile asynchronously mainUiScope.launch { val profileParams = builder.build() val result = Adapty.updateProfile(profileParams) result.onSuccess { profile -> // Profile updated successfully AppLogger.d("Custom attribute 'experience' set to: ${params.value}") }.onError { error -> // Handle the error AppLogger.e("Failed to update profile: ${error.message}") } } } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](kmp-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[このボタンのアクションへの応答](kmp-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: kmp-best-practices --- --- title: "Best practices in Kotlin Multiplatform SDK" description: "Reference patterns for integrating Adapty SDK on Kotlin Multiplatform — call order, error handling, and other production-readiness rules." --- --- # File: kmp-sdk-call-order --- --- title: "Kotlin Multiplatform SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの消失、アトリビューションの欠落、断続的な有効化エラーを防ぎます。" --- `Adapty.activate()` は、他のAdapty SDKメソッドを呼び出す前に完了している必要があります。完了するまで、SDKには状態がありません。`activate()` の前または並行して発行された呼び出しは、有効化エラーで失敗します。[Kotlin Multiplatform SDKでのエラー処理](kmp-handle-errors)を参照してください。 アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.identify()` を呼び出してください。`identify` が完了するまで、ユーザーアクションのメソッドを呼び出さないでください。`identify` と競合する呼び出しはエラーを返すか、有効化時に作成された匿名プロファイルに対して実行されます。これが発生すると、アトリビューション、`appsflyer_id` などのMMP IDやインストールの所有権が、識別済みプロファイルに必ずしも引き継がれません。アプリでユーザー認証を行わない場合は、`identify` をスキップして匿名プロファイルで作業を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。まずそれらを初期化し、UID コールバックを受け取ってから `Adapty.activate` を呼び出してください。そうしないと、MMP IDが一時的な匿名プロファイルに紐付けられ、識別済みプロファイルに必ずしも引き継がれません。AppsFlyerの詳細については、[AppsFlyer](appsflyer)を参照してください。 ## 正しい呼び出し順序 \{#the-correct-order\} どのパスをたどるかは、カスタマーユーザーIDをいつ取得できるか、およびMMPやアナリティクスSDKを使用するかどうかによって異なります。 - **ステップ2と5**:すべてのアプリで必須です。SDKを有効化してから、SDKメソッドを呼び出します。 - **ステップ1と3**:MMPやアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**:アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDがわかっている場合は、`activate()` を呼び出す前(ステップ2a)に `AdaptyConfig.Builder` に渡してください。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKを初期化する(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例:`getAppsFlyerUID`)を待ってください。 | | 2a | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | アプリ起動時、ステップ1の後、カスタマーユーザーIDがある場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").build())` (`withCustomerUserId` なし) | アプリ起動時、ステップ1の後、カスタマーユーザーIDがない場合(または収集しない場合) | Adaptが匿名プロファイルを作成します。 | | 3 | `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` (各MMPに対して) | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDが正しいプロファイルに紐付けられるために必要です。 | | 4 | `Adapty.identify("YOUR_USER_ID").onSuccess { ... }.onError { ... }` | ステップ3の後(MMPなしの場合はステップ2の後)、ステップ5の前 — 認証がある2bのパスのみ | ユーザーアクション呼び出しの前に `onSuccess` を待ってください。`identify` 中の並行呼び出しは匿名プロファイルに対して実行される可能性があります。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、そうでない場合はステップ3の後(MMPなしの場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、既存ユーザーのプレミアムアクセスの消失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対するペイウォールの返却が発生します。 ::: ## Web2appおよびウェブファネルインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入し、後でネイティブアプリをインストールした場合、デバイスの最初の `activate()` によって新しい匿名プロファイルが作成されます。このプロファイルはウェブプロファイルとリンクされていません。認証フローやインストールリファラーからアプリ起動前にカスタマーユーザーIDを解決できる場合は、直接 `AdaptyConfig.Builder` に渡してください。そうしないと、`identify("YOUR_USER_ID")` を呼び出し、さらに `restorePurchases` を呼び出すまで、デバイスからウェブ購入が見えない状態になります。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: kmp-optimize-paywall-fetching --- --- title: "Kotlin Multiplatform SDKでペイウォール取得を最適化する" description: "Adapty ペイウォールを確実に取得: Kotlin Multiplatformのタイミング、キャッシュ、フォールバックパターン。" --- Kotlin Multiplatformでペイウォールを確実に取得するには、3つのことを行う必要があります: 高速にレンダリングする、オーディエンスに合わせたペイウォールを返す、ネットワークが遅いときでも適切にフォールバックする。以下のルールは、これを実現するためのタイミング、キャッシュ、フォールバックパターンをカバーしています。 :::tip このルールは、`Adapty.activate()` と `Adapty.identify()` がすでに完了していることを前提としています。[Kotlin Multiplatform SDKでのコール順序](kmp-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨 | 非推奨 | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを一括でプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決される機会を与えた後(例: `activate` から1〜2秒後、または `setOnProfileUpdatedListener` が発火した後)に `getPaywall` を取得する。 | アプリ起動時に `getPaywall` を呼び出す。 | アトリビューションがまだ確定していない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが無効になる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待ち続ける。 | タイムアウトがない場合、接続が悪いユーザーにはネットワークが解決されるまで(またはアプリを閉じるまで)空白の画面が表示される。 | `fetchPolicy` と `loadTimeout` パラメーターについては[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-kmp)を、適切なプレースメントの選び方については[プレースメント](placements)を参照してください。 ## 接続が不安定な環境向けの調整 \{#tune-for-poor-connectivity\} 接続が継続的に不安定な市場(農村地帯、交通機関、ルーティングの影響を受ける地域)向け: - 最初の取得を除くすべての取得で `fetchPolicy = AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードのすべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発生した場合はフォールバックを受け入れる。 - ペイウォールの表示を `Adapty.getProfile()` に依存させない。`getPaywall` を独立して呼び出し、プロファイルの遅延がUIをブロックしないようにする。 --- # File: kmp-test --- --- title: "Kotlin Multiplatform SDKでテストとリリース" description: "AdaptyでKotlin MultiplatformアプリのサブスクリプションステータスをチェックするKotlin Multiplatformでのテスト方法を学びます。" --- Kotlin MultiplatformアプリにAdapty SDKを実装済みであれば、すべてが正しく設定されており、購入が期待通りに動作することを確認したいはずです。これには、SDK連携のテストと、サンドボックス環境での実際の購入フローのテストが含まれます。 ## アプリのテスト \{#test-your-app\} アプリ内課金の包括的なテストについては、プラットフォーム固有のテストガイドを参照してください:[iOSテストガイド](test-purchases-in-sandbox)および[Androidテストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しくアンロックおよびリストアされる - プライバシーとレビューの要件を満たしている --- # File: kmp-best-practices --- --- title: "Best practices in Kotlin Multiplatform SDK" description: "Reference patterns for integrating Adapty SDK on Kotlin Multiplatform — call order, error handling, and other production-readiness rules." --- --- # File: kmp-sdk-call-order --- --- title: "Kotlin Multiplatform SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの消失、アトリビューションの欠落、断続的な有効化エラーを防ぎます。" --- `Adapty.activate()` は、他のAdapty SDKメソッドを呼び出す前に完了している必要があります。完了するまで、SDKには状態がありません。`activate()` の前または並行して発行された呼び出しは、有効化エラーで失敗します。[Kotlin Multiplatform SDKでのエラー処理](kmp-handle-errors)を参照してください。 アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.identify()` を呼び出してください。`identify` が完了するまで、ユーザーアクションのメソッドを呼び出さないでください。`identify` と競合する呼び出しはエラーを返すか、有効化時に作成された匿名プロファイルに対して実行されます。これが発生すると、アトリビューション、`appsflyer_id` などのMMP IDやインストールの所有権が、識別済みプロファイルに必ずしも引き継がれません。アプリでユーザー認証を行わない場合は、`identify` をスキップして匿名プロファイルで作業を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。まずそれらを初期化し、UID コールバックを受け取ってから `Adapty.activate` を呼び出してください。そうしないと、MMP IDが一時的な匿名プロファイルに紐付けられ、識別済みプロファイルに必ずしも引き継がれません。AppsFlyerの詳細については、[AppsFlyer](appsflyer)を参照してください。 ## 正しい呼び出し順序 \{#the-correct-order\} どのパスをたどるかは、カスタマーユーザーIDをいつ取得できるか、およびMMPやアナリティクスSDKを使用するかどうかによって異なります。 - **ステップ2と5**:すべてのアプリで必須です。SDKを有効化してから、SDKメソッドを呼び出します。 - **ステップ1と3**:MMPやアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**:アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDがわかっている場合は、`activate()` を呼び出す前(ステップ2a)に `AdaptyConfig.Builder` に渡してください。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKを初期化する(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例:`getAppsFlyerUID`)を待ってください。 | | 2a | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | アプリ起動時、ステップ1の後、カスタマーユーザーIDがある場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").build())` (`withCustomerUserId` なし) | アプリ起動時、ステップ1の後、カスタマーユーザーIDがない場合(または収集しない場合) | Adaptが匿名プロファイルを作成します。 | | 3 | `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` (各MMPに対して) | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDが正しいプロファイルに紐付けられるために必要です。 | | 4 | `Adapty.identify("YOUR_USER_ID").onSuccess { ... }.onError { ... }` | ステップ3の後(MMPなしの場合はステップ2の後)、ステップ5の前 — 認証がある2bのパスのみ | ユーザーアクション呼び出しの前に `onSuccess` を待ってください。`identify` 中の並行呼び出しは匿名プロファイルに対して実行される可能性があります。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、そうでない場合はステップ3の後(MMPなしの場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、既存ユーザーのプレミアムアクセスの消失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対するペイウォールの返却が発生します。 ::: ## Web2appおよびウェブファネルインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入し、後でネイティブアプリをインストールした場合、デバイスの最初の `activate()` によって新しい匿名プロファイルが作成されます。このプロファイルはウェブプロファイルとリンクされていません。認証フローやインストールリファラーからアプリ起動前にカスタマーユーザーIDを解決できる場合は、直接 `AdaptyConfig.Builder` に渡してください。そうしないと、`identify("YOUR_USER_ID")` を呼び出し、さらに `restorePurchases` を呼び出すまで、デバイスからウェブ購入が見えない状態になります。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: kmp-optimize-paywall-fetching --- --- title: "Kotlin Multiplatform SDKでペイウォール取得を最適化する" description: "Adapty ペイウォールを確実に取得: Kotlin Multiplatformのタイミング、キャッシュ、フォールバックパターン。" --- Kotlin Multiplatformでペイウォールを確実に取得するには、3つのことを行う必要があります: 高速にレンダリングする、オーディエンスに合わせたペイウォールを返す、ネットワークが遅いときでも適切にフォールバックする。以下のルールは、これを実現するためのタイミング、キャッシュ、フォールバックパターンをカバーしています。 :::tip このルールは、`Adapty.activate()` と `Adapty.identify()` がすでに完了していることを前提としています。[Kotlin Multiplatform SDKでのコール順序](kmp-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨 | 非推奨 | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを一括でプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決される機会を与えた後(例: `activate` から1〜2秒後、または `setOnProfileUpdatedListener` が発火した後)に `getPaywall` を取得する。 | アプリ起動時に `getPaywall` を呼び出す。 | アトリビューションがまだ確定していない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが無効になる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待ち続ける。 | タイムアウトがない場合、接続が悪いユーザーにはネットワークが解決されるまで(またはアプリを閉じるまで)空白の画面が表示される。 | `fetchPolicy` と `loadTimeout` パラメーターについては[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-kmp)を、適切なプレースメントの選び方については[プレースメント](placements)を参照してください。 ## 接続が不安定な環境向けの調整 \{#tune-for-poor-connectivity\} 接続が継続的に不安定な市場(農村地帯、交通機関、ルーティングの影響を受ける地域)向け: - 最初の取得を除くすべての取得で `fetchPolicy = AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードのすべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発生した場合はフォールバックを受け入れる。 - ペイウォールの表示を `Adapty.getProfile()` に依存させない。`getPaywall` を独立して呼び出し、プロファイルの遅延がUIをブロックしないようにする。 --- # File: kmp-test --- --- title: "Kotlin Multiplatform SDKでテストとリリース" description: "AdaptyでKotlin MultiplatformアプリのサブスクリプションステータスをチェックするKotlin Multiplatformでのテスト方法を学びます。" --- Kotlin MultiplatformアプリにAdapty SDKを実装済みであれば、すべてが正しく設定されており、購入が期待通りに動作することを確認したいはずです。これには、SDK連携のテストと、サンドボックス環境での実際の購入フローのテストが含まれます。 ## アプリのテスト \{#test-your-app\} アプリ内課金の包括的なテストについては、プラットフォーム固有のテストガイドを参照してください:[iOSテストガイド](test-purchases-in-sandbox)および[Androidテストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しくアンロックおよびリストアされる - プライバシーとレビューの要件を満たしている --- # File: kmp-reference --- --- title: "Reference for Kotlin Multiplatform SDK" description: "Reference documentation for Adapty Kotlin Multiplatform SDK." --- This page contains reference documentation for Adapty Kotlin Multiplatform SDK. Choose the topic you need: - **[SDK models](https://kmp.adapty.io/adapty/)** - Data models and structures used by the SDK - **[Handle errors](kmp-handle-errors)** - Error handling and troubleshooting --- # File: kmp-handle-errors --- --- title: "Handle errors in Kotlin Multiplatform SDK" description: "Learn how to handle errors in your Kotlin Multiplatform app with Adapty." --- This page covers error handling in the Adapty Kotlin Multiplatform SDK. ## Error handling basics All Adapty SDK methods return results that can be either success or error. Always handle both cases: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // Handle success } is AdaptyResult.Error -> { val error = result.error // Handle error Log.e("Adapty", "Error: ${error.message}") } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // Handle success } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle error Log.e("Adapty", "Error: " + error.getMessage()); } }); ``` ## Common error codes | Error Code | Description | Solution | |------------|-------------|----------| | 1000 | No product IDs found | Check product configuration in dashboard | | 1001 | Network error | Check internet connection | | 1002 | Invalid SDK key | Verify your SDK key | | 1003 | Can't make payments | Device doesn't support payments | | 1004 | Product not available | Product not configured in store | ## Handle specific errors ### Network errors ```kotlin showLineNumbers Adapty.getPaywall("main") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Use paywall } is AdaptyResult.Error -> { val error = result.error when (error.code) { 1001 -> { // Network error - show offline message showOfflineMessage() } else -> { // Other errors showErrorMessage(error.message) } } } } } ``` ```java showLineNumbers Adapty.getPaywall("main", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // Use paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); switch (error.getCode()) { case 1001: // Network error - show offline message showOfflineMessage(); break; default: // Other errors showErrorMessage(error.getMessage()); break; } } }); ``` ### Purchase errors ```kotlin showLineNumbers product.makePurchase { result -> when (result) { is AdaptyResult.Success -> { val purchase = result.value // Purchase successful showSuccessMessage() } is AdaptyResult.Error -> { val error = result.error when (error.code) { 1003 -> { // Can't make payments showPaymentNotAvailableMessage() } 1004 -> { // Product not available showProductNotAvailableMessage() } else -> { // Other purchase errors showPurchaseErrorMessage(error.message) } } } } } ``` ```java showLineNumbers product.makePurchase(result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchase purchase = ((AdaptyResult.Success) result).getValue(); // Purchase successful showSuccessMessage(); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); switch (error.getCode()) { case 1003: // Can't make payments showPaymentNotAvailableMessage(); break; case 1004: // Product not available showProductNotAvailableMessage(); break; default: // Other purchase errors showPurchaseErrorMessage(error.getMessage()); break; } } }); ``` ## Error recovery strategies ### Retry on network errors ```kotlin showLineNumbers fun getPaywallWithRetry(placementId: String, maxRetries: Int = 3) { var retryCount = 0 fun attemptGetPaywall() { Adapty.getPaywall(placementId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Use paywall } is AdaptyResult.Error -> { val error = result.error if (error.code == 1001 && retryCount < maxRetries) { // Network error - retry retryCount++ Handler(Looper.getMainLooper()).postDelayed({ attemptGetPaywall() }, 1000 * retryCount) // Exponential backoff } else { // Max retries reached or other error showErrorMessage(error.message) } } } } } attemptGetPaywall() } ``` ```java showLineNumbers public void getPaywallWithRetry(String placementId, int maxRetries) { AtomicInteger retryCount = new AtomicInteger(0); Runnable attemptGetPaywall = new Runnable() { @Override public void run() { Adapty.getPaywall(placementId, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // Use paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); if (error.getCode() == 1001 && retryCount.get() < maxRetries) { // Network error - retry retryCount.incrementAndGet(); new Handler(Looper.getMainLooper()).postDelayed(this, 1000 * retryCount.get()); } else { // Max retries reached or other error showErrorMessage(error.getMessage()); } } }); } }; attemptGetPaywall.run(); } ``` ### Fallback to cached data ```kotlin showLineNumbers class PaywallManager { private var cachedPaywall: AdaptyPaywall? = null fun getPaywall(placementId: String) { Adapty.getPaywall(placementId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value cachedPaywall = paywall showPaywall(paywall) } is AdaptyResult.Error -> { val error = result.error if (error.code == 1001 && cachedPaywall != null) { // Network error - use cached paywall showPaywall(cachedPaywall!!) showOfflineIndicator() } else { // No cache available or other error showErrorMessage(error.message) } } } } } } ``` ```java showLineNumbers public class PaywallManager { private AdaptyPaywall cachedPaywall; public void getPaywall(String placementId) { Adapty.getPaywall(placementId, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); cachedPaywall = paywall; showPaywall(paywall); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); if (error.getCode() == 1001 && cachedPaywall != null) { // Network error - use cached paywall showPaywall(cachedPaywall); showOfflineIndicator(); } else { // No cache available or other error showErrorMessage(error.getMessage()); } } }); } } ``` ## Next steps - [Fix for Code-1000 noProductIDsFound error](InvalidProductIdentifiers-kmp) - [Fix for Code-1003 cantMakePayments error](cantMakePayments-kmp) - [Complete API reference](https://android.adapty.io) - Full SDK documentation --- # File: InvalidProductIdentifiers-kmp --- --- title: "Kotlin Multiplatform SDK の Code-1000 noProductIDsFound エラーの修正" description: "Adapty でサブスクリプションを管理する際の無効なプロダクト識別子エラーを解決します。" --- 1000 コードのエラー `noProductIDsFound` は、ペイウォールでリクエストしたプロダクトが App Store に登録されているにもかかわらず、購入できる状態にないことを示しています。このエラーには `InvalidProductIdentifiers` 警告が伴う場合があります。警告のみでエラーが出ていない場合は、無視して問題ありません。 `noProductIDsFound` エラーが発生している場合は、次の手順で解決してください。 ## ステップ 1. バンドル ID を確認する \{#step-2-check-bundle-id\} --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ 2. プロダクトを確認する \{#step-3-check-products\} 1. **App Store Connect** を開き、左側のメニューから [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) に移動します。 2. サブスクリプショングループ名をクリックすると、**Subscriptions** セクションにプロダクトの一覧が表示されます。 3. テスト中のプロダクトが **Ready to Submit** になっていることを確認します。なっていない場合は、[App Store のプロダクト](app-store-products)ページの手順に従ってください。 4. テーブルのプロダクト ID と、Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブに表示されているプロダクト ID を比較します。ID が一致しない場合は、テーブルからプロダクト ID をコピーして、Adapty ダッシュボードでそのプロダクト ID を使って[プロダクトを作成](create-product)してください。 ## ステップ 3. プロダクトの提供状況を確認する \{#step-4-check-product-availability\} 1. **App Store Connect** に戻り、同じ **Subscriptions** セクションを開きます。 2. サブスクリプショングループ名をクリックしてプロダクト一覧を表示します。 3. テスト中のプロダクトを選択します。 4. **Availability** セクションまでスクロールし、必要な国や地域がすべて一覧に含まれていることを確認します。 ## ステップ 4. プロダクトの価格を確認する \{#step-5-check-product-prices\} 1. 再度 **App Store Connect** の **Monetization** → **Subscriptions** セクションに移動します。 2. サブスクリプショングループ名をクリックします。 3. テスト中のプロダクトを選択します。 4. **Subscription Pricing** までスクロールし、**Current Pricing for New Subscribers** セクションを展開します。 5. 必要な価格がすべて一覧に含まれていることを確認します。 ## ステップ 5. アプリの有料ステータス、銀行口座、税務フォームがアクティブであることを確認する \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) のホームページで **Business** をクリックします。 2. 会社名を選択します。 3. スクロールして、**Paid Apps Agreement**、**Bank Account**、**Tax forms** がすべて **Active** と表示されていることを確認します。 これらの手順を実施することで、`InvalidProductIdentifiers` 警告を解消し、プロダクトをストアで公開できるようになります。 ## ステップ 6. プロダクトが動かない場合は再作成する \{#step-6-recreate-the-product-if-its-stuck\} ステップ 1〜5 をすべてパスしても — `Approved` ステータス、バンドル ID の一致、有効な API キー — SDK が `1000 noProductIDsFound` を返し続ける場合があります。その場合、プロダクトが Apple のレジストリで動かなくなっている可能性があります。App Store Connect の UI 上にはプロダクトが存在しているように見えても、StoreKit のルックアップパスに公開されていない状態になることがあります。 App Store Connect でそのプロダクトを削除し、同じプロダクト ID で再作成してください。再作成後、反映されるまで最大 24 時間かかる場合があります。 --- # File: cantMakePayments-kmp --- --- title: "Kotlin Multiplatform SDKにおけるCode-1003 cantMakePaymentエラーの修正方法" description: "Adaptyでサブスクリプションを管理する際の支払い処理エラーを解決します。" --- 1003エラー(`cantMakePayments`)は、このデバイスでアプリ内課金ができないことを示しています。 `cantMakePayments`エラーが発生している場合、通常は以下のいずれかの原因が考えられます: - デバイスの制限:このエラーはAdaptyとは無関係です。以下の解決方法を参照してください。 - オブザーバーモードの設定:`makePurchase`メソッドとオブザーバーモードは同時に使用できません。以下のセクションを参照してください。 ## 問題:デバイスの制限 \{#issue-device-restrictions\} | 問題 | 解決方法 | |-----------------------------|---------------------------------------------------------| | スクリーンタイムの制限 | [スクリーンタイム](https://support.apple.com/en-us/102470)でアプリ内課金の制限を無効にする | | アカウントの停止 | Appleサポートに連絡してアカウントの問題を解決する | | 地域の制限 | 対応地域のApp Storeアカウントを使用する | ## 問題:オブザーバーモードとmakePurchaseの併用 \{#issue-using-both-observer-mode-and-makepurchase\} 購入処理に`makePurchase`を使用している場合、オブザーバーモードを使用する必要はありません。[オブザーバーモード](observer-vs-full-mode)が必要なのは、購入ロジックを自分で実装する場合のみです。 したがって、`makePurchase`を使用している場合は、SDK有効化コードからオブザーバーモードの有効化を安全に削除できます。 --- # File: kmp-sdk-migration-guides --- --- title: "Kotlin Multiplatform SDK Migration Guides" description: "Migration guides for Adapty Kotlin Multiplatform SDK versions." --- This page contains all migration guides for Adapty Kotlin Multiplatform SDK. Choose the version you want to migrate to for detailed instructions: - **[Migrate to v3.15](migration-to-kmp-315)** --- # File: migration-to-kmp-315 --- --- title: "Adapty Kotlin Multiplatform SDK 3.15.0 移行ガイド" description: "Adapty Kotlin Multiplatform SDK 3.15.0 の移行手順" --- Adapty Kotlin Multiplatform SDK 3.15.0 はメジャーリリースであり、新機能と改善が含まれています。ただし、一部の移行作業が必要になる場合があります。 1. オブザーバークラスとメソッド名を更新する。 2. フォールバックペイウォールのメソッド名を更新する。 3. イベントハンドリングメソッドのビュークラス名を更新する。 ## オブザーバークラスとメソッド名を更新する \{#update-observer-class-and-method-names\} オブザーバークラスとその登録メソッドの名前が変更されました: ```diff - import com.adapty.kmp.AdaptyUIObserver + import com.adapty.kmp.AdaptyUIPaywallsEventsObserver - import com.adapty.kmp.models.AdaptyUIView + import com.adapty.kmp.models.AdaptyUIPaywallView - class MyAdaptyUIObserver : AdaptyUIObserver { - override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) { + class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { + override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { // handle actions } } // Set up the observer - AdaptyUI.setObserver(MyAdaptyUIObserver()) + AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` ## フォールバックペイウォールのメソッド名を更新する \{#update-fallback-paywalls-method-name\} フォールバックペイウォールを設定するメソッド名が変更されました: ```diff showLineNumbers - Adapty.setFallbackPaywalls(assetId = "fallback.json") + Adapty.setFallback(assetId = "fallback.json") .onSuccess { // Fallback paywalls loaded successfully } .onError { error -> // Handle the error } ``` ## イベントハンドリングメソッドのビュークラス名を更新する \{#update-view-class-name-in-event-handling-methods\} すべてのイベントハンドリングメソッドで、`AdaptyUIView` の代わりに新しい `AdaptyUIPaywallView` クラスを使用するようになりました: ```diff - override fun paywallViewDidAppear(view: AdaptyUIView) { + override fun paywallViewDidAppear(view: AdaptyUIPaywallView) { // Handle paywall appearance } - override fun paywallViewDidDisappear(view: AdaptyUIView) { + override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) { // Handle paywall disappearance } - override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) { + override fun paywallViewDidSelectProduct(view: AdaptyUIView, productId: String) { // Handle product selection } - override fun paywallViewDidStartPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct) { + override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) { // Handle purchase start } - override fun paywallViewDidFinishPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { + override fun paywallViewDidFinishPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { // Handle purchase result } - override fun paywallViewDidFailPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, error: AdaptyError) { + override fun paywallViewDidFailPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError) { // Add your purchase failure handling logic here } - override fun paywallViewDidFinishRestore(view: AdaptyUIView, profile: AdaptyProfile) { + override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) { // Add your successful restore handling logic here } - override fun paywallViewDidFailRestore(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your restore failure handling logic here } - override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIView, product: AdaptyPaywallProduct?, error: AdaptyError?) { + override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError?) { // Handle web payment navigation result } - override fun paywallViewDidFailLoadingProducts(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your product loading failure handling logic here } - override fun paywallViewDidFailRendering(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) { // Handle rendering error } ``` --- # End of Documentation _Generated on: 2026-07-01T16:29:19.482Z_ _Successfully processed: 50/50 files_