# FLUTTER - 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.395Z Total files: 42 --- # File: sdk-installation-flutter --- --- title: "Flutter SDK のインストールと設定" description: "サブスクリプション型アプリ向けに Flutter へ Adapty SDK をインストールするためのステップバイステップガイド。" --- Adapty SDK には、Flutter アプリへのシームレスな統合を実現する 2 つの主要モジュールが含まれています。 - **Core Adapty**: Adapty をアプリで正しく動作させるために必須の SDK です。 - **AdaptyUI**: クロスプラットフォームのペイウォールを簡単に作成できるノーコードツール、[Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合に必要なモジュールです。 :::tip Adapty SDK をモバイルアプリに統合した実際の例を見てみませんか?ペイウォールの表示や購入フローなど基本的な機能の完全なセットアップを示した[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)をご確認ください。 ::: ## 動作要件 \{#requirements\} Adapty SDK は iOS 13.0 以降をサポートしていますが、ペイウォールビルダーで作成したペイウォールを正しく表示するには iOS 15.0 以降が必要です。 :::info Adapty は Google Play Billing Library 8.x までに対応しています。デフォルトでは Google Play Billing Library v7.0.0 を使用しますが、より新しいバージョンを使用したい場合は、手動で[依存関係を追加](https://developer.android.com/google/play/billing/integrate#dependency)できます。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 ## Adapty SDK のインストール \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Flutter.svg?style=flat&logo=flutter)](https://github.com/adaptyteam/AdaptySDK-Flutter/releases) 1. `pubspec.yaml` ファイルに Adapty を追加します: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: ^ ``` 2. 以下のコマンドを実行して依存関係をインストールします: ```bash showLineNumbers title="Terminal" flutter pub get ``` 3. アプリケーションに Adapty SDK をインポートします: ```dart showLineNumbers title="main.dart" import 'package:adapty_flutter/adapty_flutter.dart'; ``` ## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} アプリのコードで Adapty SDK を有効化します。 :::note Adapty SDK の有効化は、アプリ内で一度だけ行う必要があります。 ::: **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"` を置き換えます。 または、[Adapty CLI](developer-cli) を使ってプログラムから取得することもできます: ``` npm install -g adapty adapty auth login adapty apps list ``` あるいは、直接実行する場合: ``` npx adapty auth login adapty apps list ``` - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ```dart showLineNumbers title="main.dart" void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override void initState() { _initializeAdapty(); super.initState(); } Future _initializeAdapty() async { try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY'), ); } catch (e) { // handle the error } } Widget build(BuildContext context) { return Text("Hello"); } } ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` の完了を待ってください。完全な呼び出し順序については [Flutter SDK の呼び出し順序](flutter-sdk-call-order)を参照してください。 ::: 次に、アプリにペイウォールを設定します: - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、まず下記の [AdaptyUI モジュールの有効化](#activate-adaptyui-module-of-adapty-sdk)を行い、その後[ペイウォールビルダーのクイックスタート](flutter-quickstart-paywalls)に進んでください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](flutter-quickstart-manual)を参照してください。 ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する予定があり、[AdaptyUI モジュールをインストール](sdk-installation-flutter#install-adapty-sdk)済みの場合は、AdaptyUI も有効化する必要があります: :::note AdaptyUI に関連する依存関係は、AdaptyUI が有効化されているかどうかに関わらずアプリにリンクされます。 ::: :::important コード内では、AdaptyUI を有効化する前に必ずコアの Adapty モジュールを有効化してください。 ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withActivateUI(true), // This automatically activates AdaptyUI ); ``` ## オプション設定 \{#optional-setup\} ### ログ \{#logging\} #### ログシステムを設定する \{#set-up-the-logging-system\} Adapty は、状況を把握するためにエラーやその他の重要な情報をログに記録します。利用可能なログレベルは以下のとおりです: | レベル | 説明 | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ | | `AdaptyLogLevel.none` | 何もログに記録されません。デフォルト値 | | `AdaptyLogLevel.error` | エラーのみログに記録されます | | `AdaptyLogLevel.warn` | 重大なエラーは発生しないものの注意が必要な SDK からのエラーとメッセージがログに記録されます。 | | `AdaptyLogLevel.info` | エラー、警告、およびさまざまな情報メッセージがログに記録されます。 | | `AdaptyLogLevel.verbose` | 関数呼び出しや API クエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます。 | Adapty を設定する前に、アプリ内でログレベルを設定できます: ```dart showLineNumbers title="main.dart" // Set log level before activation. // 'verbose' is recommended for development and the first production release await Adapty().setLogLevel(AdaptyLogLevel.verbose); // Or set it during configuration await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withLogLevel(AdaptyLogLevel.verbose), ); ``` ### データポリシー \{#data-policies\} Adapty は明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや各国のガイドラインに準拠するために追加のデータセキュリティポリシーを実装することができます。 #### IP アドレスの収集と共有を無効化する \{#disable-ip-address-collection-and-sharing\} Adapty モジュールを有効化する際に、`ipAddressCollectionDisabled` を `true` に設定することで、ユーザーの IP アドレスの収集と共有を無効化できます。デフォルト値は `false` です。 このパラメータは、ユーザープライバシーの強化、GDPR や CCPA などの地域のデータ保護規制への準拠、または IP ベースの機能がアプリに不要な場合の不必要なデータ収集の削減に活用できます。 ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withIpAddressCollectionDisabled(true), ); ``` #### 広告 ID の収集と共有を無効化する \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際に、`appleIdfaCollectionDisabled`(iOS)または `googleAdvertisingIdCollectionDisabled`(Android)を `true` に設定することで、広告識別子の収集を無効化できます。デフォルト値は `false` です。 このパラメータは、App Store / Play Store のポリシーへの準拠、App Tracking Transparency プロンプトの表示回避、または広告 ID に基づく広告アトリビューションや分析をアプリが必要としない場合に活用できます。 ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withAppleIdfaCollectionDisabled(true) // iOS ..withGoogleAdvertisingIdCollectionDisabled(true), // Android ); ``` #### AdaptyUI のメディアキャッシュ設定を行う \{#set-up-media-cache-configuration-for-adaptyui\} モジュールは Adapty SDK と共に自動的に有効化されます。ペイウォールビルダーを使用しない場合に AdaptyUI モジュールを無効化したいときは、有効化時に `withActivateUI(false)` を渡してください。 デフォルトでは、AdaptyUI はパフォーマンス向上とネットワーク使用量削減のために、画像や動画などのメディアをキャッシュします。カスタム設定を指定することでキャッシュの設定をカスタマイズできます。 `withMediaCacheConfiguration` を使用して、デフォルトのキャッシュサイズと有効期間を上書きできます。これはオプションです。このメソッドを呼び出さない場合、デフォルト値(ディスクサイズ 100MB、メモリカウント無制限)が使用されます。ただし、設定を使用する場合はすべてのパラメータを含める必要があります。 ```dart showLineNumbers title="main.dart" final mediaCacheConfig = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit: 2147483647, // max int value diskStorageSizeLimit: 200 * 1024 * 1024, // 200 MB ); await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withMediaCacheConfiguration(mediaCacheConfig), ); ``` **パラメータ:** | パラメータ | 必須 | 説明 | |-------------------------|----------|-----------------------------------------------------------------------------| | memoryStorageTotalCostLimit | オプション | メモリ上のキャッシュの合計サイズ(バイト単位)。デフォルトは 100 MB。 | | memoryStorageCountLimit | オプション | メモリストレージのアイテム数の上限。デフォルトは int の最大値。 | | diskStorageSizeLimit | オプション | ディスク上のファイルサイズの上限(バイト単位)。デフォルトは 100 MB。 | ### ローカルアクセスレベルを有効化する(Android) \{#enable-local-access-levels-android\} デフォルトでは、[ローカルアクセスレベル](local-access-levels)は iOS で有効、Android で無効になっています。Android でも有効化するには、`withGoogleLocalAccessLevelAllowed` を `true` に設定します: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleLocalAccessLevelAllowed(true), ); ``` ### バックアップ復元時のデータ消去 \{#clear-data-on-backup-restore\} `clearDataOnBackup` を `true` に設定すると、iCloud バックアップからアプリが復元されたことを SDK が検知し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールなど、ローカルに保存されたすべての SDK データを削除します。その後、SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴および Adapty サーバー上のユーザーデータは変更されません。 ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withClearDataOnBackup(true) // default – false ); ``` ## トラブルシューティング \{#troubleshooting\} #### Android バックアップルール(Auto Backup 設定) \{#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" #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始する Activity が非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ったときに Android が Activity を誤って再作成または再利用することがあります。これにより、購入結果が失われたり、キャンセルとして処理されたりする場合があります。 購入が正しく機能するようにするには、購入フローを開始する Activity に `standard` または `singleTop` の起動モードのみを使用し、その他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始する Activity の起動モードが `standard` または `singleTop` に設定されていることを確認してください: ```xml ``` #### Podfile の SWIFT_VERSION オーバーライドが原因で発生する Swift 6 ビルドエラー \{#swift-6-build-errors-caused-by-podfile-swift_version-override\} iOS 向けに Flutter アプリをビルドする際、Adapty pod ターゲットで Swift 6 のコンパイルエラーが発生することがあります。よくある症状としては、`AdaptyUIBuilderLogic` での `@Sendable` の不一致、Adapty 型への `Sendable` 適合の欠如、またはアクター隔離エラーなどがあります。 Adapty の pod は `s.swift_version = '6.0'` を宣言しており、ビルドに Swift 6 が必要です。アプリ独自のコードは Swift 5 のままで構いません。Swift 6 でビルドする必要があるのは Adapty の pod ターゲット(`Adapty`、`AdaptyUI`、`AdaptyUIBuilder`、`AdaptyLogger`、`AdaptyPlugin`)のみです。 最もよくある原因は、`ios/Podfile` の `post_install` フックがすべての pod ターゲットの `SWIFT_VERSION` を上書きしていることです: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **修正方法**: Adapty の pod ターゲットをオーバーライドの対象から除外します: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` その後、`ios/` ディレクトリで `pod install` を実行してリビルドしてください。 確認するには、`ios/Pods/Pods.xcodeproj` を開き、`Adapty` の pod ターゲットを選択して **Build Settings** → **Swift Language Version** を確認します。**Swift 6** と表示されているはずです。 --- # File: flutter-quickstart-paywalls --- --- title: "Flutter SDKでペイウォールを使って課金を有効にする" description: "アプリ内サブスクリプション管理のためのAdaptyセットアップクイックスタートガイド。" --- アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定です。Adaptyでは、ペイウォールがプロダクトを取得する唯一の方法ですが、この設計によりアプリのコードを変更せずにオファー内容や価格、プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールをどこでいつ表示するか(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントにペイウォールを設定し、コードからはプレースメントIDで取得します。これにより、A/B テストの実施や異なるユーザーへの異なるペイウォール表示が簡単になります。 Adaptyには、アプリ内課金を有効にする3つの方法があります。アプリの要件に応じて選択してください: | 実装方法 | 複雑さ | 使用タイミング | |------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応ペイウォールを作成](quickstart-paywalls)します。Adaptyが自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて裏側で処理します。 | | 手動作成のペイウォール | 🟡 中程度 | ペイウォールのUIはアプリのコードで実装しますが、プロダクトオファーの柔軟性を保つためにAdaptyからペイウォールオブジェクトを取得します。[ガイド](flutter-quickstart-manual)をご覧ください。 | | オブザーバーモード | 🔴 難しい | 独自の購入処理インフラがすでにあり、それを引き続き使用したい場合。オブザーバーモードにはAdaptyでの制限があることに注意してください。[記事](observer-vs-full-mode)をご覧ください。 | :::important **以下の手順は、Adaptyのペイウォールビルダーで作成したペイウォールの実装方法を説明しています。** ペイウォールビルダーを使用しない場合は、[手動作成ペイウォールでの購入処理ガイド](flutter-making-purchases)をご覧ください。 ::: Adaptyのペイウォールビルダーで作成したペイウォールを表示するには、アプリのコードで以下のことだけが必要です: 1. **ペイウォールを取得する**: Adaptyからペイウォールを取得します。 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-flutter)します。 :::tip これらの手順を最速で完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使用してペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定されたプレースメントに紐づいています。プレースメントを使うことで、異なるオーディエンスに異なるペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adaptyのペイウォールビルダーで作成したペイウォールを取得するには、以下の手順が必要です: 1. `getPaywall` メソッドを使って[プレースメント](placements)IDで `paywall` オブジェクトを取得し、`hasViewConfiguration` プロパティを使ってビルダーで作成したペイウォールかどうかを確認します。 2. `createPaywallView` メソッドを使ってペイウォールビューを作成します。ビューにはペイウォールを表示するために必要なUI要素とスタイリングが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。オフのままだと空のビュー設定が返され、ペイウォールが表示されません。 ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定が取得できたら、数行追加するだけでペイウォールを表示できます。 ペイウォールを表示するには、`createPaywallView` メソッドで作成した `view` に対して `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。再度ペイウォールを表示する必要がある場合は、`createPaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip ペイウォールの表示方法の詳細については、[ガイド](flutter-present-paywalls)をご覧ください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォール上のボタンをクリックすると、Flutter SDKは購入と復元を自動的に処理します。ただし、その他のボタンにはカスタムまたは事前定義されたIDがあり、コードでアクションを処理する必要があります。 ペイウォール画面上のプロセスを制御・監視するには、`AdaptyUIPaywallsEventsObserver` のメソッドを実装し、画面を表示する前にオブザーバーを設定します。ユーザーが何らかのアクションを実行すると `paywallViewDidPerformAction` が呼び出されるため、アプリはアクションIDに応じて応答する必要があります。 例えば、ペイウォールには通常、閉じるボタンや開くURLが含まれています(利用規約やプライバシーポリシーなど)。そのため、`Close` と `OpenUrl` のIDを持つアクションに応答する必要があります。 :::tip ボタンの[アクション](flutter-handle-paywall-actions)と[イベント](flutter-handling-events)の処理方法については、ガイドをご覧ください。 ::: ```dart showLineNumbers title="Flutter" class _PaywallScreenState extends State implements AdaptyUIPaywallsEventsObserver { @override void initState() { super.initState(); // Register this class as the paywalls event observer AdaptyUI().setPaywallsEventsObserver(this); } // This method is called when user performs an action on the paywall UI @override void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; case OpenUrlAction(url: final url): // Open the URL using url_launcher package _launchUrl(url); break; } } // Helper method to launch URLs Future _launchUrl(String url) async { try { final Uri uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } else { // Handle case where URL cannot be launched print('Could not launch $url'); } } catch (e) { // Handle any errors print('Error launching URL: $e'); } } } ``` ## 次のステップ \{#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)でテスト購入を試して、ペイウォールからテスト購入が完了できることを確認してください。 次に、[ユーザーのアクセスレベルを確認](flutter-check-subscription-status)して、適切なユーザーにペイウォールを表示したり有料機能へのアクセスを付与したりできるようにする必要があります。 ## 完全な実装例 \{#full-example\} これらのすべてのステップをアプリにまとめて統合する方法を示します。 ```dart void main() async { runApp(MaterialApp(home: PaywallScreen())); } class PaywallScreen extends StatefulWidget { @override State createState() => _PaywallScreenState(); } class _PaywallScreenState extends State implements AdaptyUIPaywallsEventsObserver { @override void initState() { super.initState(); // Register this class as the paywalls event observer AdaptyUI().setPaywallsEventsObserver(this); _showPaywallIfNeeded(); } Future _showPaywallIfNeeded() async { try { final paywall = await Adapty().getPaywall( placementId: 'YOUR_PLACEMENT_ID', ); if (!paywall.hasViewConfiguration) return; final view = await AdaptyUI().createPaywallView(paywall: paywall); await view.present(); } catch (_) { // Handle any errors (network, SDK issues, etc.) } } // This method is called when user performs an action on the paywall UI @override void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; case OpenUrlAction(url: final url): // Open the URL using url_launcher package _launchUrl(url); break; } } // Helper method to launch URLs Future _launchUrl(String url) async { try { final Uri uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } else { // Handle case where URL cannot be launched print('Could not launch $url'); } } catch (e) { // Handle any errors print('Error launching URL: $e'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Adapty Paywall Example')), body: Center( // Add a button to re-trigger the paywall for testing purposes child: ElevatedButton( onPressed: _showPaywallIfNeeded, child: Text('Show Paywall'), ), ), ); } } ``` --- # File: flutter-check-subscription-status --- --- title: "Flutter SDKでサブスクリプションステータスを確認する" description: "AdaptyでFlutterアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- 有料コンテンツへのアクセスやペイウォールの表示を判断するには、プロファイルの[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態を取得して、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ユーザーにペイウォールを表示するか有料コンテンツを見せるかを判断する際には、プロファイルの[アクセスレベル](access-level)を確認します。方法は2つあります。 - アプリ起動時など、最新のプロファイルデータをすぐに取得したい場合や強制更新したい場合は `getProfile` を呼び出す。 - **プロファイルの自動更新**を設定して、サブスクリプションステータスが変わるたびにローカルコピーを自動的に更新する。 ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得する最もシンプルな方法は、`getProfile` メソッドを使ってプロファイルにアクセスすることです。 ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### サブスクリプション更新をリッスンする \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取るには: 1. `Adapty().didUpdateProfileStream.listen()` を使ってプロファイルの変更をリッスンします。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼ばれた際に更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```dart class SubscriptionManager { AdaptyProfile? _currentProfile; SubscriptionManager() { // Listen for profile updates Adapty().didUpdateProfileStream.listen((profile) { _currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() bool hasAccess() { return _currentProfile?.accessLevels['premium']?.isActive ?? false; } } ``` :::note Adaptyはアプリ起動時にプロファイル更新ストリームのリスナーを自動的に呼び出し、デバイスがオフラインでもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携する \{#connect-profile-with-paywall-logic\} ペイウォールを表示するか有料機能へのアクセスを許可するかを即座に判断する必要がある場合、ユーザーのプロファイルを直接確認できます。このアプローチは、アプリ起動時、プレミアムセクションへの入場時、特定コンテンツを表示する前など、様々なシナリオで役立ちます。 ```dart Future _checkAccessLevel() async { try { final profile = await Adapty().getProfile(); return profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false; } catch (e) { print('Error checking access level: $e'); return false; // Show paywall if access check fails } } Future _initializePaywall() async { await _loadPaywall(); final hasAccess = await _checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } ``` ## 次のステップ \{#next-steps\} サブスクリプションステータスの追跡方法がわかったので、次は[ユーザープロファイルの操作](flutter-quickstart-identify)について学び、ユーザーが購入済みのコンテンツにアクセスできるようにしましょう。 --- # File: flutter-quickstart-identify --- --- title: "Flutter SDKでのユーザー識別" description: "FlutterでのアプリサブスクリプションのAdapty設定に関するクイックスタートガイド。" --- :::important このガイドは、独自の認証システムをお持ちの方向けです。ここでは、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回のインストールとしてカウントされます。 ## 識別済みユーザー \{#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`を`await`してください。並列呼び出しをすると`#3006 profileWasChanged`が発生するか、匿名プロファイルに対して処理が行われます。詳しくは[Flutter SDKの呼び出し順序](flutter-sdk-call-order)を参照してください。 ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### SDK有効化時 \{#during-the-sdk-activation\} SDKを有効化する時点でカスタマーユーザーIDがわかっている場合は、`identify`を別途呼び出す代わりに、`activate`メソッドに渡すことができます。 カスタマーユーザーIDがわかっていても有効化後に設定する場合、有効化時にAdaptyが新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルへ切り替わります。 既存のカスタマーユーザーID(以前に使用したもの)でも新しいものでも渡すことができます。新しいIDを渡すと、有効化時に作成された新しいプロファイルがそのカスタマーユーザーIDに自動的に紐づけられます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスのダッシュボードに影響しません。インストールはデバイスIDに基づいてカウントされるためです。 デバイスIDはストアからデバイスへのアプリの1回のインストールを表し、アプリを再インストールした場合にのみ再生成されます。 初回インストールか再インストールかに関係なく、また既存のカスタマーユーザーIDを使用するかどうかにも依存しません。 プロファイルの作成(SDK有効化時またはログアウト時)、ログイン、またはアプリの再インストールなしのアップグレードでは、追加のインストールイベントは生成されません。 デバイスではなく一意のユーザーを基準にインストールをカウントしたい場合は、**App settings**に移動して[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```dart showLineNumbers" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. ); } catch (e) { // handle the error } ``` ### ユーザーのログアウト \{#log-users-out\} ユーザーをログアウトさせるボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーをログアウトすると、そのユーザーに対して新しい匿名プロファイルが作成されます。 ::: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用してください。 ::: ### ログインなしで購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリにログインする前後の両方で購入できる場合、ログイン後もアクセスが維持されるよう対応する必要があります: 1. ログアウト中のユーザーが購入を行うと、AdaptyはそれをユーザーのAnonymous Profile IDに紐づけます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルへの切り替えを行います。 - 新しいカスタマーユーザーIDの場合(例:登録前に購入が行われた場合)、Adaptyは現在のプロファイルにカスタマーユーザーIDを割り当てるため、購入履歴がすべて維持されます。 - 既存のカスタマーユーザーIDの場合(そのカスタマーユーザーIDがすでにプロファイルに紐づいている場合)、プロファイル切り替え後に実際のアクセスレベルを取得する必要があります。識別直後に[`getProfile`](flutter-check-subscription-status)を呼び出すか、[プロファイルの更新を購読](flutter-check-subscription-status)してデータが自動的に同期されるようにしてください。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内決済のロジックを実装できました!アプリのマネタイズが成功することを願っています! Adaptyをさらに活用するために、以下のトピックを探索してみてください: - [**テスト**](troubleshooting-test-purchases):すべてが期待通りに動作することを確認する - [**オンボーディング**](flutter-onboardings):オンボーディングでユーザーを引き付けてリテンションを向上させる - [**インテグレーション**](configuration):マーケティングアトリビューションや分析サービスとワンラインで連携する - [**カスタムプロファイル属性の設定**](flutter-setting-user-attributes):ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/Bテストの実施や異なるユーザーへの異なるペイウォール表示を可能にする --- # File: adapty-sdk-integration-skill-flutter --- --- title: "SDK統合スキルを使ってFlutterアプリにAdaptyを導入する" description: "adapty-sdk-integrationスキルを使って、AIコーディングツールでFlutterアプリにAdapty SDKをエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作をした場合は、[ステップバイステップの統合ガイド](adapty-cursor-flutter)を参照してください。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-flutter --- --- title: "AIアシスタントを使ってAdaptyをFlutterアプリに統合する" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使ってAdaptyをFlutterアプリに統合するステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使ってAdaptyをFlutterアプリにステップバイステップで統合する方法を説明します。適切な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** に移動します。FlutterアプリがiOSとAndroidの両方を対象としている場合は、App StoreとGoogle Playの両方を接続してください。購入機能を動作させるために必要です。 [ストアを接続する](integrate-payments) 2. **Public SDKキーをコピーする**: Adapty ダッシュボードで **App settings → General** に移動し、**API keys** セクションを確認します。コードでは、このキーをAdapty設定に渡します。 3. **プロダクトを1つ以上作成する**: Adapty ダッシュボードで **Products** ページに移動します。コードでプロダクトを直接参照することはなく、Adaptyはペイウォールごしにプロダクトをデリバリーします。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードで **Paywalls** ページにペイウォールを作成し、**Placements** ページでプレースメントに割り当てます。コードでは、プレースメントIDを `Adapty().getPaywall()` に渡す文字列として使います。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページでプロダクトごとに設定します。コードでは `profile.accessLevels['premium']?.isActive` でチェックする文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで使えます。プロダクトによって利用できる機能が異なる場合(たとえば `basic` プランと `pro` プラン)は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip この5つが揃えばコードを書く準備は完了です。LLMに「Public SDKキーは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サーバーです。質問内容に応じて適切なドキュメントをLLMが自動的に取得するため、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 Flutter SDK ``` :::warning Context7を使えばドキュメントリンクを手動でペーストする必要はなくなりますが、実装の順序は重要です。すべてが正しく動作するよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めてください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはプレーンテキストのMarkdownとして取得できます。URLの末尾に `.md` を追加するか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例: [adapty-cursor-flutter.md](https://adapty.io/docs/ja/adapty-cursor-flutter.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が自動的にレンダリングします。 - [**手動作成のペイウォール**](flutter-making-purchases): 独自のペイウォールUIをコードで構築しつつ、プロダクトの取得と購入処理にAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラをそのまま使い、アナリティクスと統合にのみAdaptyを使います。 どれを選べばよいかわからない場合は、[クイックスタートの比較表](flutter-quickstart-paywalls)を参照してください。 ### SDKのインストールと設定 \{#install-and-configure-the-sdk\} `flutter pub add` でAdapty SDKの依存関係を追加し、Public SDKキーで有効化します。これが基盤となり、ここなしには何も動きません。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-flutter) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-flutter.md ``` :::tip[チェックポイント] - **期待される結果:** アプリがiOSとAndroidの両方でビルド・起動する。デバッグコンソールにAdaptyのアクティベーションログが表示される。 - **注意点:** 「Public API key is missing」→ プレースホルダーをApp settingsの実際のキーに置き換えたか確認する。 ::: ### ペイウォールの表示と購入の処理 \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入の処理方法によって異なります。 進める中でサンドボックスでの購入テストを都度行ってください。最後まで待たないようにしましょう。設定手順は[サンドボックスで購入テストする](test-purchases-in-sandbox)を参照してください。 **ガイド:** - [ペイウォールを使って購入を有効にする(クイックスタート)](flutter-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](flutter-get-pb-paywalls) - [ペイウォールを表示する](flutter-present-paywalls) - [ペイウォールイベントを処理する](flutter-handling-events) - [ボタンアクションに応答する](flutter-handle-paywall-actions) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-quickstart-paywalls.md - https://adapty.io/docs/ja/flutter-get-pb-paywalls.md - https://adapty.io/docs/ja/flutter-present-paywalls.md - https://adapty.io/docs/ja/flutter-handling-events.md - https://adapty.io/docs/ja/flutter-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトでペイウォールが表示される。プロダクトをタップするとサンドボックス購入ダイアログが表示される。 - **注意点:** ペイウォールが空または `getPaywall` エラー → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが割り当てられているか確認する。 ::: **ガイド:** - [カスタムペイウォールで購入を有効にする(クイックスタート)](flutter-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-flutter) - [リモートコンフィグで設計したペイウォールをレンダリングする](present-remote-config-paywalls-flutter) - [購入を行う](flutter-making-purchases) - [購入を復元する](flutter-restore-purchase) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-flutter.md - https://adapty.io/docs/ja/present-remote-config-paywalls-flutter.md - https://adapty.io/docs/ja/flutter-making-purchases.md - https://adapty.io/docs/ja/flutter-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示される。プロダクトをタップするとサンドボックス購入ダイアログが表示される。 - **注意点:** プロダクト配列が空 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、プレースメントにオーディエンスがあるか確認する。 ::: **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-flutter) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-flutter) 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-flutter.md - https://adapty.io/docs/ja/report-transactions-observer-mode-flutter.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行うと、Adapty ダッシュボードの **Event Feed** にトランザクションが表示される。 - **注意点:** イベントが表示されない → Adaptyへのトランザクション報告が行われているか、両ストアでサーバー通知が設定されているか確認する。 ::: ### サブスクリプションステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクティブなアクセスレベルを確認してプレミアムコンテンツを制限します。 **ガイド:** [サブスクリプションステータスを確認する](flutter-check-subscription-status) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックス購入後、`profile.accessLevels['premium']?.isActive` が `true` を返す。 - **注意点:** 購入後に `accessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているか確認する。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyプロファイルに紐付けて、デバイスをまたいで購入が維持されるようにします。 :::important アプリに認証機能がない場合はこのステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](flutter-quickstart-identify) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty().identify()` を呼び出した後、ダッシュボードの **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つのファイルに統合したものです。非常に大きいため、全体像が必要な場合のみ使用してください。 - Flutter専用の [`flutter-llms.txt`](https://adapty.io/docs/ja/flutter-llms.txt) と [`flutter-llms-full.txt`](https://adapty.io/docs/ja/flutter-llms-full.txt): サイト全体よりもトークンを節約できるプラットフォーム別サブセットです。 --- # File: flutter-get-pb-paywalls --- --- title: "Flutter SDKでペイウォールビルダーのペイウォールとその設定を取得する" description: "Flutter向けAdaptyでPBペイウォールを取得し、サブスクリプション管理を改善する方法を学びましょう。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアル部分をデザインした](adapty-paywall-builder)後、モバイルアプリにそれを表示できます。このプロセスの最初のステップは、プレースメントに関連付けられたペイウォールとそのビュー設定を取得することです。 :::warning 新しいペイウォールビルダーはFlutter SDK バージョン3.3.0以上が必要です。 ::: このトピックはペイウォールビルダーでカスタマイズされたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリのリモートコンフィグペイウォール用にペイウォールとプロダクトを取得する](fetch-paywalls-and-products-flutter)トピックを参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 :::
モバイルアプリでペイウォールの表示を始める前に(クリックして展開) 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成してプロダクトを追加する](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成してペイウォールを追加する](create-placement)。 4. モバイルアプリに[Adapty SDK](sdk-installation-flutter)をインストールする。
## ペイウォールビルダーで作成されたペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーを使用してペイウォールをデザインした](adapty-paywall-builder)場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングする必要はありません。このようなペイウォールには、ペイウォール内に表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてそのIDを取得し、ビュー設定を取得してからモバイルアプリに表示する必要があります。 最適なパフォーマンスを確保するために、ペイウォールとその[ビュー設定](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに提示する前に画像をダウンロードするのに十分な時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します。 ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト:`en`

|

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

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

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

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

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

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

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

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

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

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

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

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

| レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを持つ [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクト。 | ## ペイウォールビルダーで作成されたペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーで **Show on device** トグルを有効にしてください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得した後、`ViewConfiguration` が含まれているか確認してください。これはペイウォールビルダーで作成されたことを示します。この確認によってペイウォールの表示方法が決まります。`ViewConfiguration` が存在する場合はペイウォールビルダーのペイウォールとして扱い、存在しない場合は[リモートコンフィグのペイウォールとして処理します](present-remote-config-paywalls-flutter)。 ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ビューを取得したら、[ペイウォールを表示します](flutter-present-paywalls)。 ## デフォルトオーディエンス向けのペイウォールをより速く取得する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスの高速化について心配する必要はありません。ただし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのペイウォールを表示したい場合があります。 これに対処するため、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは、**All Users** オーディエンス向けの指定されたプレースメントのペイウォールを取得します。ただし、上記の[ペイウォール情報を取得する](flutter-get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)セクションで詳述しているように、`getPaywall` メソッドでペイウォールを取得することが推奨されるアプローチであることを理解することが重要です。 :::warning `getPaywall` の使用を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題が発生する可能性**:異なるアプリバージョン(現在と将来)に対して異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールの問題に直面するリスクを受け入れるかのどちらかを選択する必要があります。 - **ターゲティングの喪失**:すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを表示するため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、または独自のカスタム属性に基づくものを含む)が失われます。 ペイウォール取得の高速化という恩恵を受けるためにこれらの欠点を受け入れる場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note `getPaywallForDefaultAudience` メソッドはFlutter SDK バージョン3.2.0以降で利用可能です。 ::: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト:`en`

|

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

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

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

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

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

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

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

| ## アセットをカスタマイズする \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には事前定義されたID(`hero_image` および `hero_video`)があります。カスタムアセットバンドルでは、これらのIDを使用して要素をターゲットにし、その動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定する](custom-media)必要があります。 例えば、次のことができます: - 一部のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像が読み込まれている間にローカルのプレビュー画像を表示する。 - 動画を再生する前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty Flutter SDK をバージョン3.8.0以上にアップデートしてください。 ::: シンプルなディクショナリを使用してカスタムアセットを提供する例を示します: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customAssets: , preloadProducts: preloadProducts, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの外観にフォールバックします。 ::: ## 開発者定義タイマーを設定する \{#set-up-developer-defined-timers\} モバイルアプリでカスタムタイマーを使用するには、`AdaptyTimerResolver` プロトコルに準拠したオブジェクトを作成してください。このオブジェクトは各カスタムタイマーのレンダリング方法を定義します。必要であれば、このプロトコルにすでに準拠している `[String: Date]` ディクショナリを直接使用することもできます。以下に例を示します: ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customTimers: { 'CUSTOM_TIMER_6H': DateTime.now().add(const Duration(seconds: 3600 * 6)), 'CUSTOM_TIMER_NY': DateTime(2025, 1, 1), // New Year 2025 }, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` この例では、`CUSTOM_TIMER_NY` と `CUSTOM_TIMER_6H` はAdapity ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。`timerResolver` は、アプリが各タイマーを正しい値で動的に更新することを保証します。例えば: - `CUSTOM_TIMER_NY`:元日など、タイマー終了までの残り時間。 - `CUSTOM_TIMER_6H`:ユーザーがペイウォールを開いた時点から始まる6時間の残り時間。 --- # File: flutter-present-paywalls --- --- title: "Flutter - 新しいペイウォールビルダーのペイウォールを表示する" description: "Adaptyのマネタイズ機能を使ってFlutterアプリでペイウォールを表示します。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでレンダリングしてユーザーに表示する必要はありません。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。 :::warning このガイドは、SDK v3.2.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。ペイウォールの表示方法は、ペイウォールビルダーのバージョンやリモートコンフィグのペイウォールによって異なります。 - **リモートコンフィグのペイウォール**を表示する場合は、[リモートコンフィグで設計されたペイウォールのレンダリング](present-remote-config-paywalls)を参照してください。 ::: Adapty Flutter SDK では、ペイウォールを表示する方法が2つあります。 - **スタンドアロンスクリーン** - **埋め込みウィジェット** ## スタンドアロンスクリーンとして表示する \{#present-as-standalone-screen\} ペイウォールをスタンドアロンスクリーンとして表示するには、[`createPaywallView`](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) メソッドで作成した `view` に対して `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`createPaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 :::warning 同じ `view` を再作成せずに再利用すると、`AdaptyUIError.viewAlreadyPresented` エラーが発生する可能性があります。 ::: ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### ペイウォールを閉じる \{#dismiss-the-paywall\} プログラムからペイウォールを閉じる必要がある場合は、`dismiss()` メソッドを使用します。 ```dart showLineNumbers title="Flutter" try { await view.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### ダイアログを表示する \{#show-dialog\} Android でペイウォールビューが表示されているときは、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では、通常のアラートがペイウォールビューの背後に表示されるため、ユーザーには見えません。このメソッドを使用することで、すべてのプラットフォームでペイウォールの上に正しくダイアログが表示されます。 ```dart showLineNumbers title="Flutter" try { final action = await view.showDialog( title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', ); if (action == AdaptyUIDialogActionType.secondary) { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (e) { // handle error } ``` ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメータを渡すことで、iOS でのペイウォールの表示方法を設定できます。パラメータには `AdaptyUIIOSPresentationStyle.fullScreen`(デフォルト)または `AdaptyUIIOSPresentationStyle.pageSheet` を指定できます。 ```dart showLineNumbers try { await view.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## ウィジェット階層に埋め込む \{#embed-in-widget-hierarchy\} 既存のウィジェットツリーにペイウォールを埋め込むには、Flutter のウィジェット階層に `AdaptyUIPaywallPlatformView` ウィジェットを直接使用します。 ```dart showLineNumbers title="Flutter" AdaptyUIPaywallPlatformView( paywall: paywall, // The paywall object you fetched onDidAppear: (view) { }, onDidDisappear: (view) { }, onDidPerformAction: (view, action) { }, onDidSelectProduct: (view, productId) { }, onDidStartPurchase: (view, product) { }, onDidFinishPurchase: (view, product, purchaseResult) { }, onDidFailPurchase: (view, product, error) { }, onDidStartRestore: (view) { }, onDidFinishRestore: (view, profile) { }, onDidFailRestore: (view, error) { }, onDidFailRendering: (view, error) { }, onDidFailLoadingProducts: (view, error) { }, onDidFinishWebPaymentNavigation: (view, product, error) { }, ) ``` :::note Android プラットフォームビューを機能させるには、`MainActivity` が `FlutterFragmentActivity` を継承していることを確認してください。 ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: --- # File: flutter-handle-paywall-actions --- --- title: "Flutter SDKでボタンアクションに応答する" description: "AdaptyのFlutter SDKでペイウォールのボタンアクションを処理し、アプリのマネタイズを改善する方法を解説します。" --- ペイウォールビルダーでペイウォールを作成する場合、ボタンを適切に設定することが重要です。 1. [ペイウォールビルダーでボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに実装します。 このガイドでは、カスタムアクションと既存アクションをコードで処理する方法を説明します。 :::warning **購入と復元のみが自動的に処理されます。** ペイウォールを閉じたりリンクを開いたりする操作など、その他のボタンアクションはすべて、アプリのコードに適切な処理を実装する必要があります。 ::: ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリのコードに、`CloseAction` と `AndroidSystemBackAction` アクションのハンドラーを実装します。 :::info Flutter SDK では、`CloseAction` と `AndroidSystemBackAction` アクションはデフォルトでペイウォールを閉じる動作をします。ただし、必要に応じてコードでこの動作をオーバーライドすることもできます。たとえば、あるペイウォールを閉じると別のペイウォールが開くようにすることも可能です。 ::: ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; default: break; } } ``` ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーで **Link** 要素を追加し、**Open URL** アクションが割り当てられたボタンと同じ方法で処理します。 ::: ペイウォールからリンクを開くボタン(**Terms of use** や **Privacy policy** など)を追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当てて、開きたいURLを入力します。 2. アプリのコードに、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 ```dart // You have to install url_launcher plugin in order to handle urls: // https://pub.dev/packages/url_launcher void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) { switch (action) { case OpenUrlAction(url: final url): final Uri uri = Uri.parse(url); launchUrl(uri, mode: LaunchMode.inAppBrowserView); break; default: break; } } ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Login** アクションを割り当てます。 2. アプリのコードに、ユーザーを識別する `login` アクションのハンドラーを実装します。 ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'login'): // Handle login action Navigator.of(context).push(MaterialPageRoute(builder: (context) => LoginScreen())); break; default: break; } } ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当てて、IDを設定します。 2. アプリのコードに、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションプランや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます。 ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'openNewPaywall'): // Display another paywall break; default: break; } } ``` --- # File: flutter-handling-events --- --- title: "Flutter - ペイウォールイベントの処理" description: "Adapty を使用して Flutter でサブスクリプション関連イベントを処理し、ユーザーのインタラクションを効果的に追跡する方法を説明します。" --- :::important このガイドでは、購入・復元・プロダクト選択・ペイウォールレンダリングのイベント処理について説明します。ボタン操作(ペイウォールを閉じる、リンクを開くなど)の処理も実装する必要があります。詳細は[ボタン操作の処理に関するガイド](flutter-handle-paywall-actions)を参照してください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元を行うための追加コードは不要です。ただし、アプリが応答できるイベントが生成されます。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)やペイウォール上の購入関連アクションの通知が含まれます。これらのイベントへの対応方法を以下で説明します。 :::warning このガイドは、Adapty SDK v3.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。 ::: モバイルアプリのペイウォール画面で発生するプロセスを制御・監視するには、`AdaptyUIPaywallsEventsObserver` のメソッドを実装し、画面を表示する前にオブザーバーを設定してください。 ```javascript showLineNumbers title="Flutter" AdaptyUI().setPaywallsEventsObserver(this); ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### ユーザー生成イベント \{#user-generated-events\} #### ペイウォールの表示 \{#paywall-appeared\} このメソッドは、ペイウォールビューが画面に表示されたときに呼び出されます。 :::note iOS では、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップし、アプリ内ブラウザでウェブペイウォールが開いたときにも呼び出されます。 ::: ```javascript showLineNumbers title="Flutter" void paywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### ペイウォールの非表示 \{#paywall-disappeared\} このメソッドは、ペイウォールビューが画面から閉じられたときに呼び出されます。 :::note iOS では、ペイウォールからアプリ内ブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも呼び出されます。 ::: ```javascript showLineNumbers title="Flutter" void paywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### プロダクト選択 \{#product-selection\} プロダクトが購入のために選択された場合(ユーザーまたはシステムによる)、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) { } ```
イベントの例(クリックして展開) ```javascript { "productId": "premium_monthly" } ```
#### 購入の開始 \{#started-purchase\} ユーザーが購入プロセスを開始した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { } ```
イベントの例(クリックして展開) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
#### 購入の完了 \{#finished-purchase\} このメソッドは、購入が成功した場合、ユーザーが購入をキャンセルした場合、または購入が保留中になった場合に呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // successful purchase break; case AdaptyPurchaseResultPending(): // purchase is pending break; case AdaptyPurchaseResultUserCancelled(): // user cancelled the purchase break; default: break; } } ```
イベントの例(クリックして展開) ```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": "AdaptyPurchaseResultSuccess", "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": "AdaptyPurchaseResultPending" } } // User cancelled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "AdaptyPurchaseResultUserCancelled" } } ```
この場合は画面を閉じることを推奨します。ペイウォール画面を閉じる方法については、[ボタン操作への対応](flutter-handle-paywall-actions)を参照してください。 #### ウェブ決済ナビゲーションの完了 \{#finished-web-payment-navigation\} このメソッドは、特定のプロダクトに対して[ウェブペイウォール](web-paywall)を開こうとした後に呼び出されます。ナビゲーションの成功・失敗にかかわらず呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct? product, AdaptyError? error) { } ``` **パラメーター:** | パラメーター | 説明 | |:------------|:-------------------------------------------------------------------------------------------------------| | **product** | ウェブペイウォールが開かれた `AdaptyPaywallProduct`。`null` の場合があります。 | | **error** | ウェブペイウォールのナビゲーションが失敗した場合は `AdaptyError` オブジェクト。成功した場合は `null`。 |
イベントの例(クリックして展開) ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_navigation_failed", "message": "Failed to open web paywall", "details": { "underlyingError": "Browser unavailable" } } } ```
#### 購入の失敗 \{#failed-purchase\} このメソッドは、購入が失敗した場合(決済エラーやネットワークエラーなど)に呼び出されます。ユーザーによるキャンセルや保留中のトランザクションには**呼び出されません**。それらは `paywallViewDidFinishPurchase` で処理されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } ```
イベントの例(クリックして展開) ```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\} ユーザーが復元プロセスを開始した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidStartRestore(AdaptyUIPaywallView view) { } ``` #### 復元の成功 \{#successful-restore\} 購入の復元が成功した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { } ```
イベントの例(クリックして展開) ```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` を持っている場合は、画面を閉じることを推奨します。確認方法については[サブスクリプションのステータス](flutter-listen-subscription-changes)を、ペイウォール画面の閉じ方については[ボタン操作への対応](flutter-handle-paywall-actions)を参照してください。 #### 復元の失敗 \{#failed-restore\} 購入の復元が失敗した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { } ```
イベントの例(クリックして展開) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
### データの取得とレンダリング \{#data-fetching-and-rendering\} #### プロダクト読み込みエラー \{#product-loading-errors\} 初期化時にプロダクト配列を渡さない場合、AdaptyUI は必要なオブジェクトをサーバーから自動的に取得します。この操作が失敗した場合、AdaptyUI はこのメソッドを呼び出してエラーを通知します。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { } ```
イベントの例(クリックして展開) ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ```
#### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生した場合、このメソッドが呼び出されます。デフォルト(v3.15.2 以降)では、レンダリングエラーが発生するとペイウォールは自動的に閉じられますが、必要に応じてこの動作をオーバーライドできます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { // Default behavior: view.dismiss() // Override with custom logic if needed, for example: // - Log the error // - Show an error message to the user } ```
イベントの例(クリックして展開) ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ```
通常の状況ではこのようなエラーは発生しないため、もし遭遇した場合はお知らせください。 --- # File: flutter-use-fallback-paywalls --- --- title: "Flutter - フォールバックペイウォールを使用する" description: "ユーザーがオフラインのときや Adapty サーバーが利用できないときの対処方法" --- :::warning フォールバックペイウォールは Flutter SDK v2.11 以降でサポートされています。 ::: スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック設定ファイルをプロジェクトルートのアプリ `assets` ディレクトリに追加します。 2. 対象のペイウォールまたはオンボーディングを取得する**前に** `.setFallback` メソッドを呼び出します。 ```javascript showLineNumbers title="javascript" final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { await Adapty.setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` パラメーター: | パラメーター | 説明 | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **assetId** | フォールバック設定ファイルへのパス。 | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: flutter-localizations-and-locale-codes --- --- title: "Flutter SDKでローカライズとロケールコードを使用する" description: "グローバルなユーザーにリーチするために、アプリのローカライズとロケールコードを管理します。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが関係するシナリオはいくつかあります。たとえば、アプリの現在のローカライズに合わせた正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なることがあるため、サポートしているすべてのプラットフォームに対して内部標準を採用しています。ただし、コードが複雑なため、サーバーに何を送信して正しいローカライズを取得するか、そしてその後何が起こるかを正確に理解することが非常に重要です。そうすることで、常に期待通りの結果を受け取れます。 ## 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を呼び出す際にそのキーの値を取り出して使用します: ```dart showLineNumbers // 1. Modify your app_en.arb, app_es.arb, app_pt_br.arb files /* app_en.arb */ "adapty_paywalls_locale": "en", /* app_es.arb */ "adapty_paywalls_locale": "es", /* app_pt_br.arb */ "adapty_paywalls_locale": "pt-br", // 2. Extract and use the locale code final locale = AppLocalizations.of(context)!.adapty_paywalls_locale; // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` こうすることで、アプリの各ユーザーに対してどのローカライズが取得されるかを完全にコントロールできます。 ## ローカライズの実装:別の方法 \{#implementing-localizations-the-other-way\} ロケールコードをすべてのローカライズに対して明示的に定義しなくても、同様の(ただし同一ではない)結果を得ることができます。その場合、プラットフォームが提供する他のオブジェクトからロケールコードを取り出す方法が考えられます: ```dart showLineNumbers final locale = Localizations.localeOf(context).languageCode; // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` この方法はいくつかの理由から推奨していません: 1. iOSでは、優先言語と現在のロケールは同一ではありません。ローカライズを正しく選択させるには、Appleのロジックに依存するか(ローカライズされた文字列ファイルを使った推奨アプローチを使用していれば自動的に機能します)、自分でそのロジックを再現する必要があります。 2. Adaptyのサーバーが実際に何を受け取るかを予測するのが困難です。たとえばiOSでは、デバイスで `ar_OM@numbers='latn'` のようなロケールを取得してサーバーに送信することがあります。この場合、期待していた `ar-om` ローカライズではなく `ar` が返ってくる可能性があります。 それでもこのアプローチを使用する場合は、関連するすべてのユースケースをカバーしていることを確認してください。 --- # File: flutter-web-paywall --- --- title: "Flutter SDKにウェブペイウォールを実装する" description: "App Storeの手数料や審査なしで決済できるウェブペイウォールを設定します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン 3.6.1 以降をインストールしていることを確認してください。 ::: 自分で作成したペイウォールを使用している場合は、SDKメソッドを使ってウェブペイウォールを処理する必要があります。`.openWebPaywall`メソッドは次の動作を行います。 1. Adaptyが特定のユーザーに表示されたペイウォールとリダイレクト先のウェブページを紐付けるための一意のURLを生成します。 2. ユーザーがアプリに戻ったタイミングを追跡し、短い間隔で`.getProfile`をリクエストして、プロファイルのアクセス権が更新されたかどうかを確認します。 これにより、決済が成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効化されます。 ```dart showLineNumbers title="Flutter" try { await Adapty().openWebPaywall(product: ); // The web paywall will be opened } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` :::note `openWebPaywall`メソッドには2つのバージョンがあります。 1. `openWebPaywall(product)` — ペイウォールによってURLを生成し、プロダクトデータもURLに追加します。 2. `openWebPaywall(paywall)` — プロダクトデータを追加せずにペイウォールによってURLを生成します。Adaptyのペイウォールのプロダクトとウェブペイウォールのプロダクトが異なる場合に使用します。 ::: #### エラーの処理 \{#handle-errors\} | エラー | 説明 | 推奨アクション | |-----------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | ペイウォールにウェブ購入URLが設定されていない | Adapty ダッシュボードでペイウォールが正しく設定されているか確認してください | | AdaptyError.productWithoutPurchaseUrl | プロダクトにウェブ購入URLがない | Adapty ダッシュボードでプロダクトの設定を確認してください | | AdaptyError.failedOpeningWebPaywallUrl | ブラウザでURLを開くことができなかった | デバイスの設定を確認するか、別の購入方法を提供してください | | AdaptyError.failedDecodingWebPaywallUrl | URLのパラメータのエンコードに失敗した | URLパラメータが有効で適切にフォーマットされているか確認してください | ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} :::important アプリ内ブラウザでのウェブペイウォールの表示は、Adapty SDK v3.15 以降でサポートされています。 ::: デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、ウェブ購入ページがアプリ内に表示され、ユーザーはアプリを切り替えることなく取引を完了できます。 これを有効にするには、`in`パラメータを`.inAppBrowser`に設定します。 ```dart showLineNumbers try { await Adapty().openWebPaywall( product: , openIn: AdaptyWebPresentation.inAppBrowser, ); // The web paywall will be opened in the in-app browser } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` --- # File: flutter-troubleshoot-paywall-builder --- --- title: "Flutter SDKのペイウォールビルダーのトラブルシューティング" description: "Flutter SDKのペイウォールビルダーのトラブルシューティング" --- このガイドでは、Flutter SDK でAdapty ペイウォールビルダーを使用してデザインしたペイウォールを利用する際によく発生する問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `createPaywallView` メソッドがペイウォール設定の取得に失敗する。 **原因**: ペイウォールビルダーでデバイス表示が有効になっていない。 **解決策**: ペイウォールビルダーで **Show on device** トグルを有効にしてください。 ## ペイウォールのビュー数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールのビュー数が想定の2倍になっている。 **原因**: コード内で `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、これによりビュー数が重複してしまいます。ペイウォールビルダーでデザインされたペイウォールはアナリティクスが自動的に記録されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `logShowPaywall` を呼び出していないことを確認してください。 ## その他の問題 \{#other-issues\} **問題**: 上記に記載されていないペイウォールビルダー関連の問題が発生している。 **解決策**: 必要に応じて[移行ガイド](flutter-sdk-migration-guides)を参考にSDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: flutter-quickstart-manual --- --- title: "Flutter SDKでカスタムペイウォールの購入機能を有効にする" description: "Adapty SDKをFlutterのカスタムペイウォールに統合して、アプリ内課金を有効にします。" --- このガイドでは、Adaptyをカスタムペイウォールに統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を担います。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 最も簡単に購入機能を有効にしたい場合は、[Adapty ペイウォールビルダー](flutter-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は匿名ユーザーと識別済みユーザーを異なる方法で扱います。詳細を確認してユーザーを適切に扱えるよう、[識別クイックスタートガイド](flutter-quickstart-identify)をご覧ください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順を実行します。 1. `getPaywall` メソッドに[プレースメント](placements)IDを渡して `paywall` オブジェクトを取得する。 2. `getPaywallProducts` メソッドを使ってそのペイウォールのプロダクト配列を取得する。 ```dart showLineNumbers Future loadPaywall() async { try { final paywall = await Adapty().getPaywall(placementId: 'YOUR_PLACEMENT_ID'); final products = await Adapty().getPaywallProducts(paywall: paywall); // Use products to build your custom paywall UI } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォールでプロダクトをタップしたら、選択したプロダクトを引数に `makePurchase` メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```dart showLineNumbers Future purchaseProduct(AdaptyPaywallProduct product) async { try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // Purchase successful, profile updated break; case AdaptyPurchaseResultUserCancelled(): // User canceled the purchase break; case AdaptyPurchaseResultPending(): // Purchase is pending (e.g., user will pay offline with cash) break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる方法を提供することを求めています。 ユーザーが復元ボタンをタップしたら `restorePurchases` メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```dart showLineNumbers Future restorePurchases() async { try { final profile = await Adapty().restorePurchases(); // Restore successful, profile updated } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // 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)でテスト購入が正しく完了できることを確認してください。本番環境に近い実装例については、サンプルアプリの[PurchasesObserver](https://github.com/adaptyteam/AdaptySDK-Flutter/blob/master/example/lib/purchase_observer.dart)を参照してください。エラーハンドリング、UIオブザーバー、包括的なSDK統合を含む購入処理の実装例が確認できます。 次は、[ユーザーが購入を完了しているか確認する](flutter-check-subscription-status)ことで、ペイウォールを表示すべきか有料機能へのアクセスを許可すべきかを判断できます。 --- # File: fetch-paywalls-and-products-flutter --- --- title: "Flutter SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Flutter SDKでペイウォールとプロダクトを取得してユーザーの収益化を強化する。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズされたペイウォールの取得については、[ペイウォールビルダーのペイウォールと設定の取得](flutter-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-flutter)します。
## ペイウォール情報の取得 \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Play両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合され、モバイルアプリの特定のプレースメントで表示できます。 プロダクトを表示するには、`getPaywall`メソッドを使って[プレースメント](placements)のいずれかから[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべきIDはプレースメントIDのみです。ペイウォールはリモートで設定されるため、プロダクト数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日ペイウォールが2つのプロダクトを返し、明日3つを返した場合も、コードを変更せずにすべてを表示してください。 ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` | パラメーター | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

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

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

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

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

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

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

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

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

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

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

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

| プロダクトIDをハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクト数、特別オファー(無料トライアルなど)は随時変更される可能性があります。これらのシナリオに対応できるコードを書いてください。 例えば、最初に2つのプロダクトを取得する場合、アプリはその2つを表示してください。後で3つのプロダクトを取得した場合は、コードを変更せずに3つすべてを表示してください。ハードコードすべき唯一のものはプレースメントIDです。 レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html)オブジェクト。 | ## プロダクトの取得 \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクトの配列を取得できます: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(paywall: paywall); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む[`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html)オブジェクトのプロパティにアクセスする必要があるでしょう。以下によく使われるプロパティを示しますが、すべての利用可能なプロパティの詳細はリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライズはデバイスのロケールではなく、ユーザーが選択したストアの国に基づいています。 | | **Price** | ローカライズされた価格を表示するには、`product.price.localizedString`を使用します。このローカライズはデバイスのロケール情報に基づいています。`product.price.amount`で数値として価格にアクセスすることもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには、`product.price.currencySymbol`を使用します。 | | **Subscription Period** | 期間(週、月、年など)を表示するには、`product.subscription?.localizedPeriod`を使用します。このローカライズはデバイスのロケールに基づいています。プログラムでサブスクリプション期間を取得するには、`product.subscription?.period`を使用します。そこから`unit`列挙型にアクセスして長さ(日、週、月、年、または不明)を取得できます。`numberOfUnits`の値で期間の単位数を取得できます。例えば、四半期サブスクリプションの場合、unitプロパティには`AdaptyPeriodUnit.month`、numberOfUnitsプロパティには`3`が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれていることを示すバッジなどを表示するには、`product.subscription?.offer?.phases`プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含むことができるリストです。各フェーズオブジェクトには以下の便利なプロパティがあります:
• `paymentMode`:`AdaptyPaymentMode.freeTrial`、`AdaptyPaymentMode.payAsYouGo`、`AdaptyPaymentMode.payUpFront`、`AdaptyPaymentMode.unknown`の値を持つ列挙型。無料トライアルは`AdaptyPaymentMode.freeTrial`タイプです。
• `price`:数値としての割引価格。無料トライアルの場合は`0`になります。
• `localizedNumberOfPeriods`:オファーの長さをデバイスのロケールでローカライズした文字列。例えば、3日間のトライアルオファーはこのフィールドに`3 days`と表示されます。
• `subscriptionPeriod`:オファー期間の個別の詳細をこのプロパティで取得することもできます。オファーに対しても前のセクションと同様に機能します。
• `localizedSubscriptionPeriod`:ユーザーのロケールに合わせてフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想より時間がかかることがあります。このような状況では、ペイウォールを全く表示しないよりもスムーズなユーザー体験を確保するために、デフォルトのペイウォールを表示したい場合があります。 これに対処するために、`getPaywallForDefaultAudience`メソッドを使用できます。このメソッドは**All Users**オーディエンス向けに指定されたプレースメントのペイウォールを取得します。ただし、推奨されるアプローチは上記の[ペイウォール情報の取得](fetch-paywalls-and-products-flutter#fetch-paywall-information)セクションで説明している`getPaywall`メソッドでペイウォールを取得することであることを理解することが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題の可能性**:現在と将来の異なるアプリバージョンに異なるペイウォールを表示する必要がある場合、課題に直面する可能性があります。現在(レガシー)バージョンをサポートするペイウォールを設計するか、現在(レガシー)バージョンのユーザーがレンダリングされないペイウォールの問題に遭遇することを受け入れるかのどちらかになります。 - **ターゲティングの喪失**:すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを見ることになり、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらの欠点を受け入れてペイウォール取得の高速化メリットを享受する場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでない場合は、[上記](fetch-paywalls-and-products-flutter#fetch-paywall-information)で説明した`getPaywall`を使用してください。 ::: :::note `getPaywallForDefaultAudience`メソッドはFlutter SDKではまだサポートされていませんが、近日中にサポートが追加される予定です。 ::: | パラメーター | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

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

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

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

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

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

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

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

| --- # File: present-remote-config-paywalls-flutter --- --- title: "Flutter SDKでリモートコンフィグで設計したペイウォールを表示する" description: "Adapty Flutter SDKでリモートコンフィグペイウォールを表示し、ユーザーエクスペリエンスをパーソナライズする方法をご紹介します。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを実装する必要があります。リモートコンフィグはニーズに合わせた柔軟性を提供するため、何を含めるか、ペイウォールビューをどのように表示するかはすべてあなたが決められます。リモートコンフィグを取得するメソッドを用意しているので、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID"); final String? headerText = paywall.remoteConfig?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 必要な値をすべて取得したら、それらをレンダリングして視覚的に魅力的なページに組み立てましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにすることで、あらゆるデバイスでシームレスで使いやすい体験を提供できます。 :::warning 以下で説明するように、必ず[ペイウォールビューイベントを記録](present-remote-config-paywalls-flutter#track-paywall-view-events)してください。これにより、Adapty アナリティクスがファネルやA/B テスト用の情報を収集できるようになります。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細については、[購入を行う](flutter-making-purchases)をご覧ください。 [フォールバックペイウォールと呼ばれるバックアップペイウォールの作成](flutter-use-fallback-paywalls)をお勧めします。このバックアップは、インターネット接続がない場合やキャッシュが利用できない場合にユーザーに表示され、そのような状況でもスムーズな体験を確保します。 ## ペイウォールビューイベントを記録する \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールビューのログ記録はあなたの入力が必要です。顧客がペイウォールを見たタイミングを把握しているのはあなただけだからです。 ペイウォールビューイベントをログに記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。ファネルやA/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示している場合は、`.logShowPaywall(paywall)` を呼び出す必要はありません。 ::: ```dart showLineNumbers try { final result = await Adapty().logShowPaywall(paywall: paywall); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` リクエストパラメータ: | パラメータ | 必須かどうか | 説明 | | :---------- | :------- |:----------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクト。 | --- # File: flutter-making-purchases --- --- title: "Flutter 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)を使用していますか?** 購入は自動的に処理されるため、このステップはスキップできます。 **ステップごとのガイダンスをお探しですか?** 完全なコンテキストを含むエンドツーエンドの実装手順については、[クイックスタートガイド](flutter-implement-paywalls-manually)をご確認ください。 ::: ```dart showLineNumbers try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): if (profile.accessLevels['premium']?.isActive ?? false) { // Grant access to the paid features } break; case AdaptyPurchaseResultPending(): break; case AdaptyPurchaseResultUserCancelled(): break; default: break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------- | :------- | :-------------------------------------------------------------------------------------------------- | | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) オブジェクト。 | レスポンスパラメータ: | パラメータ | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

リクエストが成功した場合、レスポンスにはこのオブジェクトが含まれます。[AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクトは、アプリ内でのユーザーのアクセスレベル、サブスクリプション、非サブスクリプション購入に関する包括的な情報を提供します。

ユーザーが必要なアクセス権を持っているかどうかを確認するために、アクセスレベルのステータスをチェックしてください。

| :::warning **注意:** Apple の StoreKit バージョン 2.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\} ユーザーが現在のサブスクリプションを更新せず、新しいサブスクリプションを選択した場合の動作は、アプリストアによって異なります。 - App Store では、サブスクリプショングループ内でサブスクリプションが自動的に更新されます。ユーザーがあるグループのサブスクリプションを購入しつつ、別のグループのサブスクリプションをすでに持っている場合、両方のサブスクリプションが同時にアクティブになります。 - Google Play では、サブスクリプションは自動的に更新されません。以下に説明するように、モバイルアプリのコードで切り替えを管理する必要があります。 Android でサブスクリプションを別のものに切り替えるには、追加パラメータを指定して `.makePurchase()` メソッドを呼び出してください。 ```dart showLineNumbers try { final result = await adapty.makePurchase( product: product, subscriptionUpdateParams: subscriptionUpdateParams, ); // successful cross-grade } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` 追加リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :--------------------------- | :------- |:--------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | 必須 | [`AdaptyAndroidSubscriptionUpdateParameters`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyAndroidSubscriptionUpdateParameters-class.html) オブジェクト。 | サブスクリプションと置き換えモードについては、Google デベロッパードキュメントを参照してください。 - [置き換えモードについて](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アナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。
アプリにコード引き換えシートを表示するには: ```dart showLineNumbers try { await Adapty().presentCodeRedemptionSheet(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // 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)を有効にすることができます。 ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleEnablePendingPrepaidPlans(true), ); ``` --- # File: flutter-restore-purchase --- --- title: "Flutter SDKでアプリ内購入を復元する" description: "Adaptyで購入を復元し、シームレスなユーザー体験を確保する方法を学びましょう。" --- iOSとAndroidの両方における購入の復元は、ユーザーがサブスクリプションやアプリ内課金などの以前に購入したコンテンツに、再度課金されることなく再アクセスできるようにする機能です。この機能は、アプリをアンインストールして再インストールしたユーザーや、新しいデバイスに切り替えたユーザーが、再度支払いをせずに以前に購入したコンテンツにアクセスしたい場合に特に便利です。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしていない場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出してください: ```javascript showLineNumbers try { final profile = await Adapty().restorePurchases(); if (profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false) { // successful access restore } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|-----------| | **Profile** |

[`AdaptyProfile`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクト。このモデルにはアクセスレベル、サブスクリプション、および買い切り購入に関する情報が含まれています。

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

| :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-flutter --- --- title: "Flutter SDKでObserverモードを実装する" description: "AdaptyのObserverモードを実装してFlutter SDKでユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラをお持ちで、すぐにAdaptyへ完全移行する準備ができていない場合は、[Observerモード](observer-vs-full-mode)を検討してみてください。基本的な使い方では、Observerモードは高度なアナリティクスとアトリビューション・アナリティクスシステムとのシームレスな連携を提供します。 これで十分であれば、必要な作業は次の2つだけです。 1. Adapty SDKの設定時に`observerMode`パラメータを`true`に設定してObserverモードをオンにします。[Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk)のセットアップ手順に従ってください。 2. 既存の購入インフラから[トランザクションをAdaptyに報告する](report-transactions-observer-mode-flutter)。 ## Observerモードのセットアップ \{#observer-mode-setup\} 購入状態とサブスクリプションステータスを自分で管理し、Adaptyをサブスクリプションイベントやアナリティクスの送信に使用する場合は、Observerモードをオンにします。 :::important Observerモードで動作している場合、Adapty SDKはトランザクションを閉じません。そのため、必ずご自身でトランザクションの処理を行ってください。 ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withObserverMode(true) // Enable observer mode ..withLogLevel(AdaptyLogLevel.verbose), ); ``` パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observerモード](observer-vs-full-mode)を制御するboolean値。デフォルト値は`false`です。 | ## ObserverモードでAdaptyのペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adatyのペイウォールやa/bテスト機能も使用したい場合は可能ですが、Observerモードでは追加のセットアップが必要です。上記の手順に加えて、以下を行う必要があります。 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-flutter)と同様にペイウォールを表示します。 3. 購入トランザクションに[ペイウォールを関連付けます](report-transactions-observer-mode-flutter)。 --- # File: report-transactions-observer-mode-flutter --- --- title: "Flutter SDKのオブザーバーモードでトランザクションを報告する" description: "Flutter SDKのAdaptyオブザーバーモードで購入トランザクションを報告し、ユーザーインサイトと収益追跡を行います。" --- オブザーバーモードでは、Adapty SDKは既存の購入システムで行われた購入を自動で追跡することができません。アプリストアからのトランザクションを手動で報告する必要があります。分析エラーを避けるため、アプリをリリースする**前**にこの設定を行うことが重要です。 `reportTransaction`を使用して、Adaptyがトランザクションを認識できるよう各トランザクションを明示的に報告してください。 :::warning **トランザクション報告をスキップしないでください!** `reportTransaction`を呼び出さない場合、Adaptyはトランザクションを認識できず、分析に表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクション報告時に`variationId`を含めてください。これにより購入が対象のペイウォールに紐づき、正確なペイウォール分析が可能になります。 ```javascript showLineNumbers try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 |
  • iOS の場合:トランザクションの識別子。
  • Android の場合:購入の文字列識別子 `purchase.getOrderId`。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。
| | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクトの `variationId` プロパティから取得できます。 |
オブザーバーモードでは、Adapty SDKは既存の購入システムで行われた購入を自動で追跡することができません。アプリストアからのトランザクションを報告するか、復元する必要があります。分析エラーを避けるため、アプリをリリースする**前**にこの設定を行うことが重要です。 両プラットフォームで`reportTransaction`を使用して各トランザクションを明示的に報告し、Android では追加手順として`restorePurchases`を使用してAdaptyがトランザクションを認識できるようにしてください。 :::warning **トランザクション報告と購入の復元をスキップしないでください!** これらのメソッドを呼び出さない場合、Adaptyはトランザクションを認識できず、分析に表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクション報告時に`variationId`を含めてください。これにより購入が対象のペイウォールに紐づき、正確なペイウォール分析が可能になります。 ```javascript showLineNumbers // every time when calling transaction.finish() if (Platform.isAndroid) { try { await Adapty().restorePurchases(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 |
  • iOS、StoreKit 1 の場合:[SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) オブジェクト。
  • iOS、StoreKit 2 の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction) オブジェクト。
  • Android の場合:文字列識別子(purchase.getOrderId)。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。
| | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクトの `variationId` プロパティから取得できます。 |
**トランザクションの報告** - 3.1.x 以前のバージョンはApp Storeのトランザクションを自動でリッスンするため、手動での報告は不要です。 - バージョン 3.2 はオブザーバーモードをサポートしていません。 **トランザクションの報告** オブザーバーモードでAdaptyにトランザクションを報告するには、[モバイルコードでの購入の復元](flutter-restore-purchase)ページで説明しているとおり、`restorePurchases`を使用してください。 :::warning **トランザクション報告をスキップしないでください!** `restorePurchases`を呼び出さない場合、Adaptyはトランザクションを認識できず、分析に表示されず、インテグレーションにも送信されません。 ::: **ペイウォールとトランザクションの紐付け** Adapty SDKは購入のソースを特定することができません。購入処理はお客様自身が行うためです。そのため、オブザーバーモードでペイウォールやA/B テストを使用する場合は、アプリストアから受け取ったトランザクションをモバイルアプリのコード内で対応するペイウォールに紐付ける必要があります。アプリリリース前にこの設定を正しく行わないと、分析エラーが発生します。 ```javascript final transactionId = transaction.transactionIdentifier final variationId = paywall.variationId try { await Adapty().setVariationId('transactionId', variationId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ```
--- # File: flutter-troubleshoot-purchases --- --- title: "Flutter SDKでの購入のトラブルシューティング" description: "Flutter SDKでの購入のトラブルシューティング" --- このガイドでは、Flutter SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseは正常に呼び出されたが、プロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase` メソッドが正常に完了したにもかかわらず、ユーザーのプロファイルとサブスクリプションのステータスがAdaptyで更新されません。 **原因**: これは通常、Google Play ストアのセットアップが不完全またはコンフィグレーションに問題があることを示しています。 **解決策**: [Google Playのセットアップ手順](initial-android)をすべて完了していることを確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して `makePurchase` メソッドが複数回呼び出されています。 **原因**: これは通常、UIの状態管理の問題やユーザーの素早い操作によって購入フローが複数回トリガーされたときに発生します。 **解決策**: [Google Playのセットアップ手順](initial-android)をすべて完了していることを確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで `makePurchase` を使用すると `AdaptyError.cantMakePayments` が発生します。 **原因**: オブザーバーモードでは、Adaptyの `makePurchase` メソッドを使用するのではなく、購入処理をご自身で行う必要があります。 **解決策**: 購入に `makePurchase` を使用している場合は、オブザーバーモードをオフにしてください。`makePurchase` を使用するか、オブザーバーモードで購入を自分で処理するか、どちらか一方を選ぶ必要があります。詳細については、[オブザーバーモードの実装](implement-observer-mode-flutter)を参照してください。 ## 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 ストアからbilling unavailableエラーが返されています。 **原因**: このエラーはAdaptyとは無関係です。デバイスで課金が利用できないことを示すGoogle Play課金ライブラリのエラーです。 **解決策**: このエラーは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` が見つからないという問題が発生しています。 **原因**: これは通常、サンドボックステストの問題に関連しています。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。サンドボックス関連の購入完了ハンドラーの問題はこれで解決することが多いです。 ## その他の問題 \{#other-issues\} **問題**: 上記で説明していないその他の購入関連の問題が発生しています。 **解決策**: 必要に応じて、[移行ガイド](flutter-sdk-migration-guides)を使用してSDKを最新バージョンに移行してください。新しいSDKバージョンでは多くの問題が解決されています。 --- # File: flutter-identifying-users --- --- title: "Flutter 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` パラメータとして渡すだけです: ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) ); } catch (e) { // handle the error } ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後に Customer User ID を設定する \{#setting-customer-user-id-after-configuration\} SDK の設定時にユーザー ID がない場合は、`.identify()` メソッドを使っていつでも後から設定できます。このメソッドが最もよく使われるケースは、登録または認証後に匿名ユーザーから認証済みユーザーに切り替わるときです。 ```dart showLineNumbers try { await Adapty().identify(customerUserId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` リクエストパラメータ: - **Customer User ID**(必須):文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーが再度ログインするなど、一部のケースでは Adapty のサーバーにはすでにそのユーザーの情報があります。このような場合、Adapty SDK は自動的に新しいユーザーとして動作するよう切り替わります。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに渡したデータがある場合は、識別されたユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得する必要があることにも注意してください。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()` メソッドを呼び出すことで、いつでもユーザーをログアウトできます: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` その後、`.identify()` メソッドを使ってユーザーをログインできます。 ## `appAccountToken` を設定する(iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) は、App Store のトランザクションを内部ユーザー ID に紐付けるための **UUID** です。 StoreKit はすべてのトランザクションにこのトークンを関連付けるため、バックエンドで App Store のデータとユーザーを照合できます。 ユーザーごとに生成した安定した UUID を使用し、同じアカウントに対してデバイスをまたいで再利用してください。 これにより、購入と App Store の通知が正しく紐付けられます。 トークンは 2 つの方法で設定できます — SDK の起動時またはユーザーの識別時です。 :::important `appAccountToken` は必ず `customerUserId` と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### 難読化されたアカウント ID を設定する(Android) \{#set-obfuscated-account-ids-android\} Google Play では、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化されたアカウント ID が必要です。これらの ID により、Google Play はユーザー情報を匿名に保ちながら購入を識別できます。これは不正防止や分析において特に重要です。 アプリが機密性の高いユーザーデータを扱う場合、または特定のプライバシー規制に準拠する必要がある場合は、これらの ID を設定する必要があるかもしれません。難読化された ID により、Google Play は実際のユーザー識別子を公開せずに購入を追跡できます。 ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ## デバイスをまたいでユーザーを識別する \{#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: flutter-setting-user-attributes --- --- title: "Flutter SDKでユーザー属性を設定する" description: "Adaptyでユーザー属性を設定し、より正確なオーディエンスセグメンテーションを実現する方法を学びましょう。" --- メールアドレスや電話番号などのオプション属性をアプリのユーザーに設定できます。設定した属性は、ユーザー[セグメント](segments)の作成やCRMでの閲覧に活用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します。 ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setEmail("email@email.com") ..setPhoneNumber("+18888888888") ..setFirstName('John') ..setLastName('Appleseed') ..setGender(AdaptyProfileGender.other) ..setBirthday(DateTime(1970, 1, 3)); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` `updateProfile` メソッドで以前に設定した属性はリセットされません。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` で使用できるキー `` と値 `` の一覧は以下のとおりです。 | キー | 値 | |---|-----| |

email

phoneNumber

firstName

lastName

| String | | gender | 列挙型。使用できる値: `female`、`male`、`other` | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定できます。カスタム属性は通常、アプリの利用状況に関連するものです。たとえば、フィットネスアプリであれば週ごとのエクササイズ回数、語学学習アプリであればユーザーの習熟度レベルなどが考えられます。カスタム属性をセグメントに活用して、ターゲットを絞ったペイウォールやオファーを作成したり、アナリティクスでどのプロダクト指標が収益に最も影響するかを分析したりできます。 ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..setCustomStringAttribute('value1', 'key1') ..setCustomDoubleAttribute(1.0, 'key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 既存のキーを削除するには、`.withRemoved(customAttributeForKey:)` メソッドを使用します。 ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..removeCustomAttribute('key1') ..removeCustomAttribute('key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` すでに設定されているカスタム属性を確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning `customAttributes` の値は最新でない場合があります。ユーザー属性は異なるデバイスからいつでも送信できるため、最後の同期以降にサーバー上の属性が変更されている可能性があります。 ::: ### 制限事項 \{#limits\} - ユーザーあたり最大30件のカスタム属性 - キー名は最大30文字。キー名には英数字と次の文字を使用できます: `_` `-` `.` - 値は50文字以内の文字列または浮動小数点数。 --- # File: flutter-listen-subscription-changes --- --- title: "Flutter SDKでサブスクリプションステータスを確認する" description: "AdaptyでFlutterアプリのユーザーのサブスクリプションステータスを追跡・管理し、顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションステータスの追跡が簡単になります。プロダクトIDをコードに手動で埋め込む必要はありません。代わりに、アクティブな[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスをすぐに把握できます。
サブスクリプションステータスの確認を始める前に(クリックして展開) - iOS の場合、[App Store Server Notifications](enable-app-store-server-notifications) を設定してください - Android の場合、[リアルタイム デベロッパー通知(RTDN)](enable-real-time-developer-notifications-rtdn) を設定してください
## アクセスレベルと AdaptyProfile オブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクトのプロパティです。アプリ起動時([ユーザーを識別する](flutter-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があるたびに更新することをおすすめします。こうすることで、都度リクエストを送ることなくプロファイルオブジェクトを利用できます。 プロファイルの更新通知を受け取るには、以下の[サブスクリプションステータス更新のリッスン](flutter-listen-subscription-changes)セクションで説明しているプロファイル変更のリスニングを設定してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()` メソッドを使用します。 ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- | ------------------------------------------------------------ | | Profile |

[AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクト。通常は、ユーザーがアプリのプレミアムアクセス権を持っているかどうかを判断するために、プロファイルのアクセスレベルのステータスだけを確認すれば十分です。

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

| `.getProfile()` メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリごとに複数のアクセスレベルを設定できます。たとえば、ニュースアプリでトピックごとに独立したサブスクリプションを販売する場合、「sports」と「science」というアクセスレベルを作成できます。ただし、多くの場合はアクセスレベルは1つで十分であり、その場合はデフォルトの「premium」アクセスレベルを使用するだけで問題ありません。 デフォルトの「premium」アクセスレベルを確認する例を示します。 ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); if (profile?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### サブスクリプションステータス更新のリッスン \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adaptyはイベントを発火します。 Adaptyからメッセージを受け取るには、追加の設定が必要です。 ```javascript showLineNumbers Adapty().didUpdateProfileStream.listen((profile) { // handle any changes to subscription state }); ``` Adaptyはアプリ起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されているキャッシュは、プロファイルのサブスクリプションステータスを保存します。そのため、サーバーが利用できない場合でも、キャッシュされたデータからプロファイルのサブスクリプションステータスを取得できます。 ただし、キャッシュから直接データをリクエストすることはできません。SDKは1分ごとにサーバーへ定期的にクエリを送信し、プロファイルに関する更新や変更を確認します。新しいトランザクションやその他の更新など変更があった場合は、サーバーとの同期を保つためにキャッシュデータへ反映されます。 --- # File: flutter-deal-with-att --- --- title: "Flutter SDK での ATT の処理" description: "Flutter で Adapty を使い始めて、サブスクリプションの設定と管理を効率化しましょう。" --- アプリが AppTrackingTransparency フレームワークを使用しており、ユーザーにアプリのトラッキング認可リクエストを表示する場合は、[認可ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)を Adapty に送信する必要があります。 ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setAppTrackingTransparencyStatus(AdaptyIOSAppTrackingTransparencyStatus.authorized); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::warning この値は変更されたときにできるだけ早く送信することを強くおすすめします。そうすることで、設定済みのインテグレーションにデータがタイムリーに送信されます。 ::: --- # File: kids-mode-flutter --- --- title: "Flutter SDKのキッズモード" description: "AppleとGoogleのポリシーに準拠するためにキッズモードを簡単に有効化。Flutter SDKではIDFA、GAID、広告データを収集しません。" --- Flutterアプリが子ども向けの場合、[Apple](https://developer.apple.com/kids/)および[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広告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\} ポリシーに準拠するために、ユーザーのIDFA(iOS向け)、GAID/AAID(Android向け)、およびIPアドレスの収集を無効化してください。 **Android:SDK設定を更新する** ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') // highlight-start ..withGoogleAdvertisingIdCollectionDisabled(true), // set to `true` ..withIpAddressCollectionDisabled(true), // set to `true` // highlight-end ); } catch (e) { // handle the error } ``` **iOS:CocoaPodsを使用してキッズモードを有効にする** 1. Podfileを更新します。 - `post_install`セクションが**ない**場合は、以下のコードブロック全体を追加してください。 - `post_install`セクションが**ある**場合は、ハイライトされた行をそこにマージしてください。 ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. 以下のコマンドを実行して変更を適用します。 ```sh showLineNumbers title="Shell" pod install ``` --- # File: flutter-get-onboardings --- --- title: "Flutter SDK でオンボーディングを取得する" description: "Flutter 向け Adapty でオンボーディングを取得する方法を説明します。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアル部分をデザイン](design-onboarding)したら、Flutter アプリに表示できます。この処理の最初のステップは、以下で説明するように、プレースメントに関連付けられたオンボーディングとそのビュー設定を取得することです。 始める前に、次の点を確認してください。 1. [Adapty Flutter SDK](sdk-installation-flutter) バージョン 3.8.0 以降がインストールされていること。 2. [オンボーディングを作成](create-onboarding)していること。 3. オンボーディングを[プレースメント](placements)に追加していること。 ## オンボーディングを取得する \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得して表示する必要のある設定を含むコンテナとして保存されます。このコンテナは、表示されるコンテンツ、表示方法、ユーザーのインタラクション(クイズの回答やフォームへの入力など)の処理方法といった、エクスペリエンス全体を管理します。また、コンテナは分析イベントを自動的に追跡するため、ビュートラッキングを別途実装する必要はありません。 パフォーマンスを最大限に発揮するため、ユーザーに表示する前に画像のダウンロードを完了できるよう、早めにオンボーディング設定を取得してください。 オンボーディングを取得するには、`getOnboarding` メソッドを使用します。 ```dart showLineNumbers try { final onboarding = await Adapty().getOnboarding(placementId: "YOUR_PLACEMENT_ID"); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` 次に、`createOnboardingView` メソッドを呼び出して、表示するビューを取得します。 :::warning `createOnboardingView` メソッドの結果は一度しか使用できません。再度使用する必要がある場合は、`createOnboardingView` メソッドを新たに呼び出してください。再作成せずに 2 回呼び出すと、`AdaptyUIError.viewAlreadyPresented` エラーが発生する場合があります。 ::: ```dart showLineNumbers try { final onboardingView = await Adapty().createOnboardingView(onboarding: onboarding); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

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

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

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

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

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

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

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

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

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

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

| レスポンスパラメーター: | パラメーター | 説明 | |:----------|:-----| | Onboarding | オンボーディングの識別子と設定、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyOnboarding`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyOnboarding-class.html) オブジェクト。 | ## デフォルトオーディエンスのオンボーディングでフェッチを高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ瞬時に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、オーディエンスやオンボーディングが多数あり、ユーザーのインターネット接続が遅い場合、オンボーディングの取得に想定より時間がかかる場合があります。そのような状況では、オンボーディングをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのオンボーディングを表示したい場合があります。 この問題を解決するために、`getOnboardingForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けオンボーディングを取得します。ただし、推奨されるアプローチは、上記の[オンボーディングを取得する](#fetch-onboarding)セクションで説明したように、`getOnboarding` メソッドでオンボーディングを取得することです。 :::warning `getOnboardingForDefaultAudience` の代わりに `getOnboarding` の使用を検討してください。後者には重要な制限があります: - **互換性の問題**: 複数のアプリバージョンをサポートする際に問題が生じる場合があります。後方互換性のあるデザインが必要になるか、古いバージョンで表示が崩れる可能性を受け入れる必要があります。 - **パーソナライズなし**: "All Users" オーディエンスのコンテンツのみ表示され、国、アトリビューション、またはカスタム属性に基づくターゲティングが行われません。 ユースケースにおいて高速なフェッチがこれらのデメリットを上回る場合は、以下に示すように `getOnboardingForDefaultAudience` を使用してください。それ以外の場合は、[上記](#fetch-onboarding)の説明に従って `getOnboarding` を使用してください。 ::: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboardingForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |------------|---------|------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

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

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

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

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

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

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

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

| --- # File: flutter-present-onboardings --- --- title: "Flutter SDKでオンボーディングを表示する" description: "コンバージョンを高めるためにオンボーディングを効果的に表示する方法を学びましょう。" --- ビルダーでオンボーディングをカスタマイズした場合、Flutter アプリのコードでレンダリング処理を記述しなくても、ユーザーに表示できます。カスタマイズ済みのオンボーディングには、表示する内容と表示方法がすべて含まれています。 始める前に、以下を確認してください: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0 以降がインストールされていること。 2. [オンボーディングが作成済み](create-onboarding)であること。 3. オンボーディングが[プレースメント](placements)に追加済みであること。 Adapty Flutter SDK では、オンボーディングを表示する方法が2つあります: - **スタンドアロン画面** - **埋め込みウィジェット** ## スタンドアロン画面として表示する \{#present-as-standalone-screen\} オンボーディングをスタンドアロン画面として表示するには、`createOnboardingView` メソッドで作成した `onboardingView` に対して `onboardingView.present()` メソッドを使用します。各 `view` は一度しか使用できません。再度オンボーディングを表示する必要がある場合は、`createOnboardingView` をもう一度呼び出して新しい `onboardingView` インスタンスを作成してください。 :::warning 同じ `onboardingView` を再作成せずに再利用すると、`AdaptyUIError.viewAlreadyPresented` エラーが発生することがあります。 ::: ```javascript showLineNumbers title="Flutter" try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### オンボーディングを閉じる \{#dismiss-the-onboarding\} プログラムでオンボーディングを閉じる必要がある場合は、`dismiss()` メソッドを使用します: ```dart showLineNumbers title="Flutter" try { await onboardingView.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメータを渡すことで、iOS でのオンボーディングの表示方法を設定できます。このパラメータには `AdaptyUIIOSPresentationStyle.fullScreen`(デフォルト)または `AdaptyUIIOSPresentationStyle.pageSheet` を指定できます。 ```dart showLineNumbers try { await onboardingView.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## ウィジェットツリーに埋め込む \{#embed-in-widget-hierarchy\} 既存のウィジェットツリーにオンボーディングを埋め込むには、Flutter のウィジェット階層内で `AdaptyUIOnboardingPlatformView` ウィジェットを直接使用します。 ```javascript showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, // The onboarding object you fetched onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` :::note Android のプラットフォームビューを動作させるには、`MainActivity` が `FlutterFragmentActivity` を継承していることを確認してください: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: ## オンボーディング中のローダー \{#loader-during-onboarding\} オンボーディングを表示する際、ビューが初期化される間、スプラッシュ画面とオンボーディングの間に短いローディング画面が表示されることがあります。用途に応じてこれをさまざまな方法で制御できます。 #### onDidFinishLoading を使用してスプラッシュ画面を制御する \{#control-splash-screen-using-ondidfinishloading\} :::note このアプローチは、オンボーディングをウィジェットとして埋め込む場合にのみ利用できます。スタンドアロン画面として表示する場合には使用できません。 ::: 推奨されるクロスプラットフォームのアプローチは、オンボーディングが完全に読み込まれるまでスプラッシュ画面またはカスタムオーバーレイを表示し続け、その後手動で非表示にする方法です。 埋め込みウィジェットを使用する場合は、ウィジェットの上に独自のウィジェットをオーバーレイし、`onDidFinishLoading` が発火したタイミングでオーバーレイを非表示にします: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Hide your custom splash screen or overlay here }, // ... other callbacks ) ``` ### ネイティブローダーをカスタマイズする \{#customize-native-loader\} :::important このアプローチはプラットフォーム固有であり、ネイティブ UI コードのメンテナンスが必要です。アプリで既に別のネイティブレイヤーをメンテナンスしている場合を除き、推奨しません。 ::: デフォルトのローダー自体をカスタマイズしたい場合は、プラットフォーム固有のレイアウトに置き換えることができます。このアプローチでは、Android と iOS それぞれに個別の実装が必要です: - **iOS**: Xcode プロジェクトに `AdaptyOnboardingPlaceholderView.xib` を追加する - **Android**: `res/layout` に `adapty_onboarding_placeholder_view.xml` を作成し、プレースホルダーを定義する ## オンボーディング内のリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディング内のリンクの開き方のカスタマイズは、Adapty SDK v3.15.1 以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開かれます。これにより、アプリを切り替えることなくウェブページを表示できるシームレスなユーザー体験が提供されます。 外部ブラウザでリンクを開くようにしたい場合は、`externalUrlsPresentation` パラメータを `AdaptyWebPresentation.externalBrowser` に設定することでこの動作をカスタマイズできます: ```dart showLineNumbers title="Flutter" final onboardingView = await AdaptyUI().createOnboardingView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser ); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` ## セーフエリアのパディングを無効にする(Android) \{#disable-safe-area-paddings-android\} デフォルトでは、Android デバイスでオンボーディングビューはステータスバーやナビゲーションバーなどのシステム UI 要素を避けるためにセーフエリアのパディングを自動的に適用します。この動作を無効にしてレイアウトを完全に制御したい場合は、アプリに boolean リソースを追加することで設定できます: 1. `android/app/src/main/res/values` に移動します。`bools.xml` ファイルが存在しない場合は作成します。 2. 以下のリソースを追加します: ```xml false ``` この変更はアプリ内のすべてのオンボーディングにグローバルに適用されます。 --- # File: flutter-handling-onboarding-events --- --- title: "Flutter SDKでオンボーディングイベントを処理する" description: "AdaptyのFlutterでオンボーディング関連イベントを処理する。" --- ビルダーで設定されたオンボーディングは、アプリが対応できるイベントを生成します。これらのイベントをどのように処理するかは、使用しているプレゼンテーション方式によって異なります。 - **フルスクリーン表示**: すべてのオンボーディングビューのイベントを処理するグローバルイベントオブザーバーのセットアップが必要 - **埋め込みウィジェット**: ウィジェット内のインラインコールバックパラメーターを通じてイベントを処理 始める前に、以下を確認してください: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0以降がインストールされていること。 2. [オンボーディングが作成されている](create-onboarding)こと。 3. オンボーディングが[プレースメント](placements)に追加されていること。 ## フルスクリーン表示のイベント \{#full-screen-presentation-events\} ### イベントオブザーバーの設定 \{#set-up-event-observer\} フルスクリーンオンボーディングのイベントを処理するには、`AdaptyUIOnboardingsEventsObserver`を実装して、表示前に設定します: ```javascript showLineNumbers title="Flutter" AdaptyUI().setOnboardingsEventsObserver(this); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### イベントの処理 \{#handle-events\} オブザーバーに以下のメソッドを実装します: ```javascript showLineNumbers title="Flutter" void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { // Onboarding finished loading } void onboardingViewDidFailWithError( AdaptyUIOnboardingView view, AdaptyError error, ) { // Handle loading errors } void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle close action view.dismiss(); } void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle custom actions } void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle user input updates } void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { // Track analytics events } ``` ## 埋め込みウィジェットのイベント \{#embedded-widget-events\} `AdaptyUIOnboardingPlatformView`を使用する場合、ウィジェット内のインラインコールバックパラメーターを通じてイベントを処理できます。イベントはウィジェットのコールバックとグローバルオブザーバー(設定されている場合)の両方に送信されますが、グローバルオブザーバーは任意です: ```javascript showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Onboarding finished loading }, onDidFailWithError: (error) { // Handle loading errors }, onCloseAction: (meta, actionId) { // Handle close action }, onPaywallAction: (meta, actionId) { _openPaywall(actionId); }, onCustomAction: (meta, actionId) { // Handle custom actions }, onStateUpdatedAction: (meta, elementId, params) { // Handle user input updates }, onAnalyticsEvent: (meta, event) { // Track analytics events }, ) ``` ## イベントの種類 \{#event-types\} 以下のセクションでは、使用しているプレゼンテーション方式に関わらず処理できる各種イベントについて説明します。 ### カスタムアクションの処理 \{#handle-custom-actions\} ビルダーでは、ボタンに **custom** アクションを追加してIDを割り当てることができます。 このIDをコードで使用し、カスタムアクションとして処理できます。たとえば、**Login** や **Allow notifications** などのカスタムボタンをユーザーがタップすると、デリゲートメソッド `onboardingController` が `.custom(id:)` ケースでトリガーされ、`actionId` パラメーターにはビルダーの **Action ID** が入ります。"allowNotifications" のような独自のIDを作成できます。 ```javascript // Full-screen presentation void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { switch (actionId) { case 'login': _login(); break; case 'allow_notifications': _allowNotifications(); break; } } // Embedded widget onCustomAction: (meta, actionId) { _handleCustomAction(actionId); } ```
イベント例(クリックして展開) ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ```
### オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このイベントがトリガーされます: ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { print('Onboarding loaded: ${meta.onboardingId}'); } // Embedded widget onDidFinishLoading: (meta) { print('Onboarding loaded: ${meta.onboardingId}'); } ```
イベント例(クリックして展開) ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ```
### オンボーディングのクローズ \{#closing-onboarding\} ユーザーが **Close** アクションが割り当てられたボタンをタップしたとき、オンボーディングはクローズされたと見なされます。 :::important ユーザーがオンボーディングをクローズしたときの動作を管理する必要があります。たとえば、オンボーディング自体の表示を停止する処理が必要です。 ::: ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { await view.dismiss(); } // Embedded widget onCloseAction: (meta, actionId) { Navigator.of(context).pop(); } ```
イベント例(クリックして展開) ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
### ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合は、このイベントを処理してください。クローズ後にペイウォールを開く場合は、クローズアクションを処理してイベントデータに依存せずにペイウォールを開く方が簡単です。 ::: オンボーディング内でペイウォールを扱う最もシームレスな方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです: iOSでは、一度に表示できるビュー(ペイウォールまたはオンボーディング)は1つだけです。オンボーディングの上にペイウォールを表示すると、バックグラウンドのオンボーディングをプログラムで操作できなくなります。オンボーディングをdismissしようとすると、代わりにペイウォールが閉じられ、オンボーディングが表示されたままになります。これを避けるために、ペイウォールを表示する前に必ずオンボーディングビューをdismissしてください。 ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } Future _openPaywall(String actionId) async { // Implement your paywall opening logic here } // Embedded widget onPaywallAction: (meta, actionId) { _openPaywall(actionId); } ```
イベント例(クリックして展開) ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ```
### ナビゲーションのトラッキング \{#tracking-navigation\} オンボーディングフロー中にナビゲーション関連のイベントが発生すると、アナリティクスイベントを受け取ります: ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { trackEvent(event.type, meta.onboardingId); } // Embedded widget onAnalyticsEvent: (meta, event) { trackEvent(event.type, meta.onboardingId); } ``` `event` オブジェクトは以下のいずれかのタイプになります: |タイプ | 説明 | |------------|-------------| | `onboardingStarted` | オンボーディングが読み込まれたとき | | `screenPresented` | いずれかの画面が表示されたとき | | `screenCompleted` | 画面が完了したとき。オプションの `elementId`(完了した要素の識別子)とオプションの `reply`(ユーザーからの返答)を含む。ユーザーが画面を離れるためのアクションを行ったときにトリガーされる。 | | `secondScreenPresented` | 2番目の画面が表示されたとき | | `userEmailCollected` | 入力フィールドからユーザーのメールアドレスが収集されたときにトリガーされる | | `onboardingCompleted` | ユーザーが `final` IDを持つ画面に到達したときにトリガーされる。このイベントが必要な場合は、[最後の画面に `final` IDを割り当てる](design-onboarding)。 | | `unknown` | 認識されないイベントタイプの場合。`name`(不明なイベントの名前)と `meta`(追加のメタデータ)を含む | 各イベントには以下の `meta` 情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内の現在の画面の位置 | | `screensTotal` | フロー内の画面の合計数 |
イベント例(クリックして展開) ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
--- # File: flutter-onboarding-input --- --- title: "Flutter SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使ってFlutterアプリでオンボーディングのデータを保存・活用する方法を説明します。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onStateUpdatedAction` メソッドが呼び出されます。フィールドの種類をコード内で保存または処理できます。 例: ```dart // フルスクリーン表示 void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Process data } // 埋め込みウィジェット onStateUpdatedAction: (meta, elementId, params) { // Process data } ``` アクションのフォーマットは[こちら](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyUIOnboardingPlatformView/onStateUpdatedAction.html)を参照してください。
保存されたデータの例(実装によってフォーマットが異なる場合があります) ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ```
## ユースケース \{#use-cases\} ### ユーザープロファイルにデータを追加する \{#enrich-user-profiles-with-data\} 入力されたデータをすぐにユーザープロファイルと紐付け、同じ情報を二度聞かないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](flutter-setting-user-attributes)する必要があります。 たとえば、`name` というIDのテキストフィールドでユーザーに名前を入力してもらい、その値をユーザーの名(first name)として設定したい場合や、`email` フィールドでメールアドレスを入力してもらう場合、アプリのコードは次のようになります。 ```dart showLineNumbers // フルスクリーン表示 void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // 埋め込みウィジェット onStateUpdatedAction: (meta, elementId, params) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、オンボーディング完了後にユーザーに表示するペイウォールをカスタマイズすることもできます。 たとえば、スポーツの経験について質問し、異なるユーザーグループに対して異なるCTAやプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、選択肢に意味のあるIDを割り当てます。 2. IDに基づいてクイズの回答を処理し、ユーザーに[カスタム属性を設定](flutter-setting-user-attributes)します。 ```dart showLineNumbers // フルスクリーン表示 void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // 埋め込みウィジェット onStateUpdatedAction: (meta, elementId, params) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](flutter-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[そのボタンのアクションへのレスポンス](flutter-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: flutter-sdk-call-order --- --- title: "Flutter SDK のコール順序" description: "Adapty SDK メソッドを正しい順序でコールすることで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的な #2002 エラーを防ぎます。" --- `Adapty().activate()` が完了してから、他の Adapty SDK メソッドを呼び出してください。解決されるまで SDK には状態がありません。`activate()` より前、または並行して発行されたコールはすべて [`#2002 notActivated`](error-handling-on-flutter-react-native-unity#custom-network-codes) でエラーになります。 アプリがユーザー認証を行い、起動後に customer user ID を収集する場合は、そのタイミングで `Adapty().identify()` を呼び出してください。`identify` が解決されるまでユーザーアクションメソッドを呼び出してはいけません。`identify` と競合するコールは [`#3006 profileWasChanged`](error-handling-on-flutter-react-native-unity#custom-network-codes) でエラーになるか、アクティベーション時に作成された匿名プロファイルに対して実行されてしまいます。これが起きると、アトリビューション、`appsflyer_id` などの MMP ID、およびインストールの所有権が識別済みプロファイルに引き継がれないことがあります。アプリがユーザー認証を行わない場合は `identify` をスキップし、匿名プロファイルのまま使用し続けてください。 MMP やアナリティクス SDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。それらを先に初期化し、UID コールバックを受け取ってから `Adapty().activate` を呼び出してください。そうしないと MMP ID が一時的な匿名プロファイルに記録され、識別済みプロファイルに必ずしも引き継がれません。AppsFlyer の詳細については [AppsFlyer](appsflyer) をご覧ください。 ## 正しい順序 \{#the-correct-order\} どのパスをたどるかは、customer user ID をいつ取得できるか、および MMP やアナリティクス SDK を使用するかどうかの 2 点によって決まります。 - **ステップ 2 と 5**: すべてのアプリで必須です。SDK をアクティベートしてから SDK メソッドを呼び出します。 - **ステップ 1 と 3**: MMP やアナリティクス SDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ 4**: アプリがユーザー認証を行い、起動後に customer user ID を収集する場合のみ必要です。 アプリ起動時に customer user ID が分かっている場合は、`activate()` に直接渡してください(ステップ 2a)。このパスでは匿名プロファイルが作成されないため、ステップ 4 は不要です。 | ステップ | コール | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP またはアナリティクス SDK(AppsFlyer、Adjust、PostHog、Branch)を初期化する | アプリ起動時、最初に | MMP の UID コールバック(例: `getAppsFlyerUID`)を待ちます。 | | 2a | `Adapty().activate(configuration: ...)` に `withCustomerUserId` を設定して呼び出す | アプリ起動時、ステップ 1 の後、customer user ID が分かっている場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty().activate(configuration: ...)` を `withCustomerUserId` なしで呼び出す | アプリ起動時、ステップ 1 の後、customer user ID が分からない場合(または収集しない場合) | Adapty が匿名プロファイルを作成します。 | | 3 | 各 MMP に対して `Adapty().setIntegrationIdentifier(key: ..., value: ...)` を呼び出す | ステップ 2 の後、ユーザーアクションコールの前 | MMP ID が正しいプロファイルに記録されるために必要です。 | | 4 | `await Adapty().identify(customerUserId)` | ステップ 3 の後(MMP がない場合はステップ 2 の後)、ステップ 5 の前 — 認証ありのパス 2b の場合のみ | 必ず `await` してください。`identify` 中の並行コールは `#3006 profileWasChanged` を引き起こします。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ 4 の後、それ以外はステップ 3 の後(MMP がない場合はステップ 2 の後) | これらのコールには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、復帰ユーザーのプレミアムアクセスが失われたり、プロファイルに `appsflyer_id` が記録されなかったり、間違ったオーディエンスに対してペイウォールが返されたりする原因になります。 ::: ## Web2app およびウェブファネル経由のインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブのチェックアウト(Stripe、Paddle)で購入してからネイティブアプリをインストールする場合、デバイス上で最初に `activate()` を呼び出すと新しい匿名プロファイルが作成されます。このプロファイルはウェブのプロファイルとは紐付けられません。アプリ起動前に(認証フローやインストールリファラーから)customer user ID を解決できる場合は、`activate()` に直接渡してください。そうでない場合、`identify("YOUR_USER_ID")` を呼び出してから `restorePurchases` を実行するまで、ウェブでの購入はデバイス上で表示されません。 各ウェブチェックアウトで送信するメタデータについては以下をご覧ください。 - [Stripe](stripe) - [Paddle](paddle) --- # File: flutter-optimize-paywall-fetching --- --- title: "Flutter SDKでペイウォールの取得を最適化する" description: "Adapty ペイウォールを確実に取得する: Flutter向けのタイミング、キャッシュ、フォールバックパターン。" --- Flutter での確実なペイウォール取得には、高速なレンダリング、オーディエンスターゲットされたペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバックという3つの要素が必要です。以下のルールでは、それを実現するためのタイミング、キャッシュ、フォールバックパターンについて説明します。 :::tip これらのルールは、`Adapty().activate()` と `Adapty().identify()` がすでに解決済みであることを前提としています。[Flutter SDK のコール順序](flutter-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | こうする | こうしない | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを同時にプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決される機会を得た後(例: `activate` から1〜2秒後、または `didUpdateProfileStream` が発火した後)に `getPaywall` を呼び出す。 | `runApp` の前に `main()` で `getPaywall` を呼び出す。 | アトリビューションがまだ反映されていない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが暗黙的にバイパスされる。 | | `loadTimeout` を設定し、すべてのプレースメントに対して[フォールバックペイウォール](fallback-paywalls)を構成する。 | `getPaywall` を無期限に待機する。 | タイムアウトがない場合、接続状況の悪いユーザーはネットワークが解決されるまで(またはアプリを閉じるまで)白紙の画面を見続ける。 | `fetchPolicy` および `loadTimeout` パラメーターのリファレンスについては[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-flutter)を、適切なプレースメントの選択については[プレースメント](placements)を参照してください。 ## 接続状況が悪い環境向けのチューニング \{#tune-for-poor-connectivity\} 接続状況が慢性的に悪い市場(農村部、移動中、ルーティングの問題がある地域)向けには: - 最初の取得以外のすべての取得で `fetchPolicy: AdaptyPaywallFetchPolicy.returnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードですべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発火した場合はフォールバックを受け入れる。 - `getProfile()` にペイウォールの表示を依存させない。`getPaywall` を独立して呼び出すことで、プロファイルの取得が遅くてもUIをブロックしないようにする。 --- # File: flutter-show-aa-targeted-paywall --- --- title: "FlutterSDKで初回起動時にApple Ads向けペイウォールを表示する" description: "Flutterで初回起動時、Apple Adsのアトリビューションを短時間待ってからペイウォールを表示し、タイムアウト時はデフォルトオーディエンスにフォールバックします。AdaptyProfile.appliedAttributionSourcesを使用します。" --- Apple Ads (AA) のアトリビューションは `Adapty().activate()` の後に非同期で届きます。初回起動時はまだ届いていないことが多いため、すぐに `getPaywall` を呼び出すと、Adapty はデフォルトオーディエンスに基づいてリクエストを解決してしまい、Apple Ads ユーザーが AA セグメント向けペイウォールを見逃してしまいます。ペイウォールを表示してから差し替えるのではなく、何も表示する前に AA アトリビューションを少しの間待ちましょう。アトリビューションが短いタイムアウト内に届けばターゲット向けペイウォールを、届かなければデフォルトオーディエンスのペイウォールを表示します。`AdaptyProfile.appliedAttributionSources` を使うと、AA アトリビューションが適用済みかどうかを確認できます。 ## 始める前に \{#before-you-start\} 必要なもの: - Adapty Flutter SDK **3.17.0** 以降。 - AdaptyでアプリのApple Adsが設定済みであること。詳しくは[Apple Ads](apple-search-ads)を参照してください。 ## 仕組み \{#how-it-works\} `Adapty().activate()` を呼び出すと、SDKはバックグラウンドでApple Ads(AA)のアトリビューション情報をAppleに問い合わせ、その結果をAdaptyのバックエンドに転送します。AAがそのプロファイルのアクティブなアトリビューションソースになると、SDKは`didUpdateProfileStream`リスナーに更新済みの`AdaptyProfile`を届けます。このとき、`appliedAttributionSources`リストには`AdaptyAttributionSource.appleAds`が含まれています。 初回起動時には、次の2つのケースを処理する必要があります: 1. **タイムアウト内にアトリビューションが届いた場合。** `getPaywall` を呼び出すと、Adapty が Apple Ads のオーディエンスに対してリクエストを解決し、ターゲットのペイウォールを返します。 2. **先にタイムアウトが経過した場合。** 代わりにデフォルトオーディエンスのペイウォールを表示し、Apple Ads のアトリビューションがないユーザーを待たせないようにしましょう。`getPaywallForDefaultAudience` はセグメント処理を待たずに即座に返します。 `appliedAttributionSources` は空になることがあります。これは次のいずれかを意味します: - このプロファイルに対する Apple Ads のアトリビューションがまだ処理されていない、または - アトリビューション自体が届いていない。 いずれの場合も、`getPaywallForDefaultAudience` は安全に呼び出せます — プロファイルの状態に関わらず、デフォルトオーディエンス向けのペイウォールを返します。 :::important この待機が発生するのは初回起動時のみです。Apple Ads のアトリビューションが一度記録されると、プロファイルに永続的に保存されます。2回目以降の起動では、キャッシュされたプロファイルには既に `appliedAttributionSources` に `AdaptyAttributionSource.appleAds` が含まれているため、アトリビューションのパスはすぐに解決され、`getPaywall` は遅延なく Apple Ads セグメント向けのペイウォールを返します。 ::: ## 実装 \{#implementation\} 初回起動時は `AdaptyAttributionSource.appleAds` を待ち、ハードタイムアウトを設定してください。Apple Ads のアトリビューションが届かなかった場合でも、該当ユーザーにはペイウォールを表示する必要があります。 1. **SDKを有効化する。** [Flutter SDKのインストールと設定](sdk-installation-flutter)を参照してください。 2. **`Adapty().didUpdateProfileStream.listen(…)`でプロファイルの更新を購読する。** リスナーをまだ設定していない場合は、[サブスクリプションの更新をリッスンする](flutter-check-subscription-status#listen-to-subscription-updates)を参照してください。 3. **`appliedAttributionSources`に`AdaptyAttributionSource.appleAds`が現れるのを監視する。** それが現れたら、`getPaywall`でペイウォールを読み込みます — AdaptyはAAセグメント済みのバリアントを返します: ```dart final subscription = Adapty().didUpdateProfileStream.listen((profile) async { if (!profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) return; final paywall = await Adapty().getPaywall(placementId: placementId); // セグメント済みのペイウォールを表示し、サブスクリプションとタイマーをキャンセルする }); ``` `didUpdateProfileStream` はブロードキャストストリームであり、過去のイベントを再生しません。そのため、`getProfile()` を使って現在のプロファイルも一度確認してください。アプリを再起動した場合、保存済みのアトリビューションはすでに適用済みのため、再度イベントは発行されません。 4. **サブスクリプションと並行して3〜5秒のタイマーを起動します。** タイマーが`AdaptyAttributionSource.appleAds`の受信より先に発火した場合は、代わりに`getPaywallForDefaultAudience`を使用してデフォルトオーディエンスのペイウォールを読み込みます。最初に解決した方のペイウォールを表示し、もう一方のパスをキャンセルして、ペイウォールが二重に取得されないようにします。ネットワークリクエストが失敗してもユーザーが行き詰まらないよう、プレースメントに[フォールバックペイウォール](flutter-use-fallback-paywalls)を設定してください。 ## 完全な実装例 \{#complete-example\} 以下の実装では、アトリビューションとタイムアウトを競合させながら、デフォルトオーディエンス向けのペイウォールを並行してプリフェッチし、適切なペイウォールを返します。呼び出し元は単一の関数を待つだけでよく、コールサイトでリスナーやステートフラグを管理する必要はありません。 - アトリビューションが `timeout` 以内に届いた場合、`getPaywall` を通じてセグメント化されたペイウォールを返します。 - `timeout` が先に経過した場合、`getPaywallForDefaultAudience` を通じてプリフェッチ済みのデフォルトオーディエンス向けペイウォールを返します。 ```dart title="apple_ads_paywall.dart" /// Returns the Apple Ads-segmented paywall if attribution is applied within /// [timeout], otherwise the default-audience paywall. Call after Adapty().activate(). Future getPaywallOrDefault({ required String placementId, required Duration timeout, }) { // Prefetch the default-audience paywall right away so the timeout path resolves // without an extra network round-trip. `getPaywallForDefaultAudience` skips the // wait for segmentation data. `..ignore()` keeps an unused prefetch from surfacing // as an unhandled error; the error still reaches the caller if this paywall wins. final defaultPaywall = Adapty().getPaywallForDefaultAudience(placementId: placementId)..ignore(); final completer = Completer(); late final StreamSubscription subscription; late final Timer timer; void resolve(Future paywall) { if (completer.isCompleted) return; timer.cancel(); subscription.cancel(); completer.complete(paywall); } void onProfile(AdaptyProfile profile) { if (profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) { resolve(Adapty().getPaywall(placementId: placementId)); } } // Attribution path: react to profile updates as attribution is applied. subscription = Adapty().didUpdateProfileStream.listen(onProfile); // The stream is a broadcast stream and doesn't replay, so check the current // profile too — on relaunches attribution is already stored and won't re-emit. Adapty().getProfile().then(onProfile).ignore(); // Timeout path: fall back to the prefetched default-audience paywall. timer = Timer(timeout, () => resolve(defaultPaywall)); return completer.future; } ``` スプラッシュ画面から呼び出し、解決後にペイウォールを表示します: ```dart try { final paywall = await getPaywallOrDefault( placementId: 'YOUR_PLACEMENT_ID', timeout: const Duration(seconds: 5), ); // present the paywall } on AdaptyError catch (adaptyError) { // handle the error or show a fallback paywall } catch (e) { // handle the error } ``` `timeout` を調整して、ペイウォールが表示されるまでユーザーを待たせる時間を設定してください。ほとんどのユーザーはApple Adsのアトリビューションを持っていないため、設定したタイムアウトの全時間を待つことになります。3〜5秒が現実的なバランスです。アトリビューションが来る場合は、通常、アプリ起動から数秒以内に届きます。 アプリがすでに別の目的(例:[サブスクリプションステータスの確認](flutter-check-subscription-status#listen-to-subscription-updates))で `didUpdateProfileStream` をリッスンしている場合、変更する必要はありません。`didUpdateProfileStream` はブロードキャストストリームなので、複数の独立したリスナーが互いに影響を与えることなく使用できます。 --- # File: flutter-test --- --- title: "Flutter SDK でのテストとリリース" description: "AdaptyでFlutterアプリのサブスクリプション状態を確認する方法を説明します。" --- Flutter アプリに Adapty SDK をすでに組み込んでいる場合は、すべてが正しく設定されており、iOS と Android の両プラットフォームで購入が期待どおりに機能することを確認するテストを行いましょう。これには、SDK の統合テストと、Apple のサンドボックス環境および Google Play のテスト環境を使った実際の購入フローのテストが含まれます。 ## アプリをテストする \{#test-your-app\} アプリ内課金の包括的なテストについては、プラットフォーム別のテストガイドを参照してください: [iOS テストガイド](test-purchases-in-sandbox) および [Android テストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist) に従って以下を確認してください: - ストアの接続とサーバー通知が設定されている - 購入が完了し、Adapty に報告されている - アクセスが正しくアンロックおよび復元される - プライバシーおよびレビュー要件を満たしている --- # File: InvalidProductIdentifiers-flutter --- --- title: "Flutter 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** になっていることを確認します。 4. テーブルのプロダクト ID と Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブのプロダクト ID を比較します。ID が一致しない場合は、テーブルからプロダクト ID をコピーし、Adapty ダッシュボードでそれを使って[プロダクトを作成](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-flutter --- --- title: "Flutter SDKにおけるコード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: flutter-migration-guide-310 --- --- title: "Flutter Adapty SDK 3.10.0 への移行ガイド" description: "" --- Adapty SDK 3.10.0 はメジャーリリースであり、いくつかの改善が含まれていますが、移行作業が必要になる場合があります。 1. `makePurchase` メソッドを、個別のパラメーターの代わりに `AdaptyPurchaseParameters` を使用するように更新する。 2. `AdaptyPaywall` モデル内の `vendorProductIds` を `productIdentifiers` に置き換える。 ## makePurchase メソッドの更新 \{#update-makepurchase-method\} `makePurchase` メソッドは、個別の `subscriptionUpdateParams` および `isOfferPersonalized` 引数の代わりに `AdaptyPurchaseParameters` を使用するようになりました。これにより、型の安全性が向上し、将来的に購入パラメーターを拡張しやすくなります。 ```diff showLineNumbers - final purchaseResult = await adapty.makePurchase( - product: product, - subscriptionUpdateParams: subscriptionUpdateParams, - isOfferPersonalized: true, - ); + final parameters = AdaptyPurchaseParametersBuilder() + ..setSubscriptionUpdateParams(subscriptionUpdateParams) + ..setIsOfferPersonalized(true) + ..setObfuscatedAccountId('your-account-id') + ..setObfuscatedProfileId('your-profile-id'); + final purchaseResult = await adapty.makePurchase( + product: product, + parameters: parameters.build(), + ); ``` 追加のパラメーターが不要な場合は、次のようにシンプルに記述できます。 ```dart showLineNumbers final purchaseResult = await adapty.makePurchase( product: product, ); ``` ## AdaptyPaywall モデルの使用方法の更新 \{#update-adaptypaywall-model-usage\} `vendorProductIds` プロパティは非推奨となり、`productIdentifiers` が推奨されるようになりました。新しいプロパティは、単純な文字列の代わりに `AdaptyProductIdentifier` オブジェクトを返すため、プロダクト情報がより構造化されています。 ```diff showLineNumbers - paywall.vendorProductIds.map((vendorId) => - ListTextTile(title: vendorId) - ).toList() + paywall.productIdentifiers.map((productId) => + ListTextTile(title: productId.vendorProductId) + ).toList() ``` `AdaptyProductIdentifier` オブジェクトは `vendorProductId` プロパティを通じてベンダープロダクト ID にアクセスでき、同等の機能を維持しながら将来の拡張に向けてより良い構造を提供します。 ## 後方互換性 \{#backward-compatibility\} どちらの変更も後方互換性を維持しています。 - `makePurchase` の旧パラメーターは非推奨ですが、引き続き機能します - `vendorProductIds` プロパティは非推奨ですが、引き続きアクセス可能です - 既存のコードは動作し続けますが、非推奨の警告が表示されます 新しい API を使用するようにコードを更新することを推奨します。これにより、将来の互換性が確保され、改善された型の安全性と拡張性のメリットを活用できます。 --- # File: flutter-migration-guide-38 --- --- title: "Adapty Flutter SDK を v3.8 へ移行する" description: "Adapty Flutter SDK v3.8 へ移行して、パフォーマンス向上と新しいマネタイズ機能を利用しましょう。" --- Adapty SDK 3.8.0 はメジャーリリースで、いくつかの改善が加えられています。ただし、移行作業が必要になる場合があります。 1. オブザーバークラスとメソッド名を更新する。 2. フォールバックペイウォールのメソッド名を更新する。 3. イベントハンドリングメソッドのビュークラス名を更新する。 ## オブザーバークラスとメソッド名を更新する \{#update-observer-class-and-method-names\} オブザーバークラスとその登録メソッドの名前が変更されました: ```diff showLineNumbers - class MyObserver extends AdaptyUIObserver { + class MyObserver extends AdaptyUIPaywallsEventsObserver { @override void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) { // Handle action } } // Register observer - AdaptyUI().setObserver(this); + AdaptyUI().setPaywallsEventsObserver(this); ``` ## フォールバックペイウォールのメソッド名を更新する \{#update-fallback-paywalls-method-name\} フォールバックペイウォールを設定するメソッドが簡略化されました: ```diff showLineNumbers try { - await Adapty.setFallbackPaywalls(assetId); + await Adapty.setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## イベントハンドリングメソッドのビュークラス名を更新する \{#update-view-class-name-in-event-handling-methods\} すべてのイベントハンドリングメソッドで、`AdaptyUIView` の代わりに新しい `AdaptyUIPaywallView` クラスが使用されるようになりました: ```diff showLineNumbers - void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) + void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) - void paywallViewDidSelectProduct(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidSelectProduct(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidStartPurchase(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidFinishPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyProfile profile) + void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyProfile profile) - void paywallViewDidFailPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyError error) + void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) - void paywallViewDidFinishRestore(AdaptyUIView view, AdaptyProfile profile) + void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) - void paywallViewDidFailRestore(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) - void paywallViewDidFailLoadingProducts(AdaptyUIView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) + void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) - void paywallViewDidFailRendering(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) ``` --- # File: migration-to-flutter-sdk-34 --- --- title: "Adapty Flutter SDK を v3.4 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Flutter SDK v3.4 に移行します。" --- Adapty SDK 3.4.0 はメジャーリリースであり、お客様側での移行手順が必要な改善が含まれています。 ## フォールバックペイウォールファイルを更新する \{#update-fallback-paywall-files\} 新しい SDK バージョンとの互換性を確保するため、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新されたフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の既存のフォールバックペイウォールを[新しいファイルに置き換え](flutter-use-fallback-paywalls)ます。 ## オブザーバーモードの実装を更新する \{#update-implementation-of-observer-mode\} オブザーバーモードを使用している場合は、その実装を更新してください。 以前は、トランザクションを Adapty に報告するために異なるメソッドが使用されていました。新しいバージョンでは、Android と iOS の両方で `reportTransaction` メソッドを一貫して使用する必要があります。このメソッドは各トランザクションを Adapty に明示的に報告し、認識されることを保証します。ペイウォールが使用された場合は、バリエーション ID を渡してトランザクションをペイウォールに紐付けてください。 :::warning **トランザクションの報告をスキップしないでください!** `reportTransaction` を呼び出さない場合、Adapty はトランザクションを認識せず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: ```diff showLineNumbers - // every time when calling transaction.finish() - if (Platform.isAndroid) { - try { - await Adapty().restorePurchases(); - } on AdaptyError catch (adaptyError) { - // handle the error - } catch (e) { - } - } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter330 --- --- title: "Adapty Flutter SDK を v3.3 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Flutter SDK v3.3 に移行します。" --- Adapty SDK 3.3.0 はメジャーリリースであり、いくつかの改善が加えられましたが、移行作業が必要になる場合があります。 1. フォールバックペイウォールを提供するメソッドを更新する。 2. `getProductsIntroductoryOfferEligibility` メソッドを削除する。 3. Adjust、AirBridge、Amplitude、AppMetrica、Appsflyer、Branch、Facebook Ads、Firebase and Google Analytics、Mixpanel、OneSignal、Pushwoosh のインテグレーション設定を更新する。 4. Observer モードの実装を更新する。 ## フォールバックペイウォールを提供するメソッドを更新する \{#update-method-for-providing-fallback-paywalls\} 以前は、メソッドにフォールバックペイウォールを JSON 文字列(`jsonString`)として渡していましたが、現在はローカルのフォールバックファイルへのパス(`assetId`)を渡すように変更されました。 ```diff showLineNumbers import 'dart:async' show Future; import 'dart:io' show Platform; -import 'package:flutter/services.dart' show rootBundle; -final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; -final jsonString = await rootBundle.loadString(filePath); +final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { - await adapty.setFallbackPaywalls(jsonString); + await adapty.setFallbackPaywalls(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 完全なコード例については、[フォールバックペイウォールを使用する](flutter-use-fallback-paywalls)ページをご覧ください。 ## `getProductsIntroductoryOfferEligibility` メソッドを削除する \{#remove-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 より前は、ユーザーが適格かどうかに関わらず、プロダクトオブジェクトには常にオファーが含まれていました。そのため、オファーを使用する前に適格性を手動で確認する必要がありました。 現在は、ユーザーが適格な場合にのみプロダクトオブジェクトにオファーが含まれます。つまり、適格性を確認する必要がなくなりました。オファーが存在していれば、ユーザーは適格です。 ## サードパーティインテグレーションの SDK 設定を更新する \{#update-third-party-integration-sdk-configuration\} Adapty Flutter SDK 3.3.0 以降でインテグレーションが正しく動作するよう、以下のセクションに従って各インテグレーションの SDK 設定を更新してください。 ### Adjust 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Adjust インテグレーションの SDK 設定](adjust#connect-your-app-to-adjust)をご覧ください。 ```diff showLineNumbers import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_config.dart'; try { final adid = await Adjust.getAdid(); if (adid == null) { // handle the error } + await Adapty().setIntegrationIdentifier( + key: "adjust_device_id", + value: adid, + ); final attributionData = await Adjust.getAttribution(); var attribution = Map(); if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!; if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!; if (attributionData.network != null) attribution['network'] = attributionData.network!; if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!; if (attributionData.creative != null) attribution['creative'] = attributionData.creative!; if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!; if (attributionData.costType != null) attribution['costType'] = attributionData.costType!; if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString(); if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!; if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!; - Adapty().updateAttribution( - attribution, - source: AdaptyAttributionSource.adjust, - networkUserId: adid, - ); + await Adapty().updateAttribution(attribution, source: "adjust"); } catch (e) { // handle the error } on AdaptyError catch (adaptyError) { // handle the error } ``` ### AirBridge 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AirBridge インテグレーションの SDK 設定](airbridge#connect-your-app-to-airbridge)をご覧ください。 ```diff showLineNumbers import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart'; final deviceUUID = await Airbridge.state.deviceUUID; try { - final builder = AdaptyProfileParametersBuilder() - ..setAirbridgeDeviceId(deviceUUID); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "airbridge_device_id", + value: deviceUUID, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Amplitude 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Amplitude インテグレーションの SDK 設定](amplitude#sdk-configuration)をご覧ください。 ```diff showLineNumbers import 'package:amplitude_flutter/amplitude.dart'; final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); final deviceId = await amplitude.getDeviceId(); final userId = await amplitude.getUserId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setAmplitudeDeviceId(deviceId) - ..setAmplitudeUserId(userId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "amplitude_user_id", + value: userId, + ); + await Adapty().setIntegrationIdentifier( + key: "amplitude_device_id", + value: deviceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### AppMetrica 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppMetrica インテグレーションの SDK 設定](appmetrica#sdk-configuration)をご覧ください。 ```diff showLineNumbers import 'package:appmetrica_plugin/appmetrica_plugin.dart'; final deviceId = await AppMetrica.deviceId; if (deviceId != null) { try { - final builder = AdaptyProfileParametersBuilder() - ..setAppmetricaDeviceId(deviceId) - ..setAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID"); - - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_device_id", + value: deviceId, + ); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_profile_id", + value: "YOUR_ADAPTY_CUSTOMER_USER_ID", + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` ### AppsFlyer 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppsFlyer インテグレーションの SDK 設定](appsflyer#connect-your-app-to-appsflyer)をご覧ください。 ```diff showLineNumbers import 'package:appsflyer_sdk/appsflyer_sdk.dart'; AppsflyerSdk appsflyerSdk = AppsflyerSdk(); appsflyerSdk.onInstallConversionData((data) async { try { final appsFlyerUID = await appsFlyerSdk.getAppsFlyerUID(); - await Adapty().updateAttribution( - data, - source: AdaptyAttributionSource.appsflyer, - networkUserId: appsFlyerUID, - ); + await Adapty().setIntegrationIdentifier( + key: "appsflyer_id", + value: appsFlyerUID, + ); + + await Adapty().updateAttribution(data, source: "appsflyer"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } }); appsflyerSdk.initSdk( registerConversionDataCallback: true, registerOnAppOpenAttributionCallback: true, registerOnDeepLinkingCallback: true, ); ``` ### Branch 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Branch インテグレーションの SDK 設定](branch#connect-your-app-to-branch)をご覧ください。 ```diff showLineNumbers FlutterBranchSdk.initSession().listen((data) async { try { + await Adapty().setIntegrationIdentifier( + key: "branch_id", + value: , + ); - await Adapty().updateAttribution(data, source: AdaptyAttributionSource.branch); + await Adapty().updateAttribution(data, source: "branch"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ); ``` ### Firebase and Google Analytics 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Firebase and Google Analytics インテグレーションの SDK 設定](firebase-and-google-analytics)をご覧ください。 ```diff showLineNumbers final appInstanceId = await FirebaseAnalytics.instance.appInstanceId; try { - final builder = AdaptyProfileParametersBuilder() - ..setFirebaseAppInstanceId(appInstanceId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "firebase_app_instance_id", + value: appInstanceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Mixpanel 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Mixpanel インテグレーションの SDK 設定](mixpanel#sdk-configuration)をご覧ください。 ```diff showLineNumbers final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true); final distinctId = await mixpanel.getDistinctId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setMixpanelUserId(distinctId); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "mixpanel_user_id", + value: distinctId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### OneSignal 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[OneSignal インテグレーションの SDK 設定](onesignal#sdk-configuration)をご覧ください。 ```diff showLineNumbers OneSignal.shared.setSubscriptionObserver((changes) { final playerId = changes.to.userId; if (playerId != null) { - final builder = - AdaptyProfileParametersBuilder() - ..setOneSignalPlayerId(playerId); - // ..setOneSignalSubscriptionId(playerId); try { - Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "one_signal_player_id", + value: playerId, + ); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle error } } }); ``` ### Pushwoosh 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Pushwoosh インテグレーションの SDK 設定](pushwoosh#sdk-configuration)をご覧ください。 ```diff showLineNumbers final hwid = await Pushwoosh.getInstance.getHWID; - final builder = AdaptyProfileParametersBuilder() - ..setPushwooshHWID(hwid); try { - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "pushwoosh_hwid", + value: hwid, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## Observer モードの実装を更新する \{#update-observer-mode-implementation\} ペイウォールとトランザクションを紐付ける方法を更新してください。以前は `setVariationId` メソッドを使って `variationId` を割り当てていましたが、現在は新しい `reportTransaction` メソッドでトランザクションを記録する際に `variationId` を直接含めることができます。最終的なコード例については、[Observer モードでペイウォールを購入トランザクションに関連付ける](report-transactions-observer-mode-flutter)をご覧ください。 :::warning `reportTransaction` メソッドを使ってトランザクションを必ず記録してください。この手順を省略すると、Adapty はトランザクションを認識できず、アクセスレベルの付与、アナリティクスへの記録、インテグレーションへの送信がいずれも行われません。この手順は必須です! ::: ```diff showLineNumbers try { - await Adapty().setVariationId("YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID"); + // every time when calling transaction.finish() + await Adapty().reportTransaction( + "YOUR_TRANSACTION_ID", + variationId: "PAYWALL_VARIATION_ID", // optional + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter-sdk-v3 --- --- title: "Adapty Flutter SDK v3.0 への移行" description: "より良いパフォーマンスと新しいマネタイズ機能のために、Adapty Flutter SDK v3.0 に移行しましょう。" --- Adapty SDK v3.0 では、ペイウォールを作成するための新しいノーコードツール [Adapty ペイウォールビルダー](adapty-paywall-builder) がサポートされました。最大限の柔軟性と豊富なデザイン機能により、ペイウォールをより効果的かつ収益性の高いものにできます。 :::info AdaptyUI ライブラリは非推奨となり、AdaptySDK の一部として組み込まれました。 ::: ## AdaptyUI SDK の削除 \{#remove-adaptyu-sdk\} 1. AdaptyUI は Adapty SDK のモジュールになったため、`pubspec.yaml` ファイルから `adapty_ui_flutter` を削除してください。 ```diff showLineNumbers dependencies: + adapty_flutter: ^3.2.1 - adapty_flutter: ^2.10.3 - adapty_ui_flutter: ^2.1.3 ``` 2. 以下を実行します。 ```bash showLineNumbers title="Bash" flutter pub get ``` ## Adapty SDK の設定 \{#configure-adapty-sdks\} これまでは、Adapty SDK の設定に `Adapty-Info.plist` および `AndroidManifest.xml` ファイルを使用する必要がありました。 現在は、追加ファイルは不要です。代わりに、アクティベーション時に必要なパラメータをすべて指定できます。 Adapty SDK の設定は、通常アプリのライフサイクル開始時に一度だけ行います。 ### Adapty SDK の Adapty モジュールをアクティベートする \{#activate-adapty-module-of-adapty-sdk\} 1. アプリケーションから AdaptyUI SDK のインポートを次のように削除します。 ```diff showLineNumbers import 'package:adapty_flutter/adapty_flutter.dart'; - import 'package:adapty_ui_flutter/adapty_ui_flutter.dart'; ``` 2. Adapty SDK のアクティベーションを次のように更新します。 ```diff showLineNumbers try { - Adapty().activate(); + await Adapty().activate( + configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') + ..withLogLevel(AdaptyLogLevel.debug) + ..withObserverMode(false) + ..withCustomerUserId(null) + ..withIdfaCollectionDisabled(false) + ..withIpAddressCollectionDisabled(false), + ); } catch (e) { // handle the error } ``` パラメータ: | パラメータ | 必須/任意 | 説明 | | ----------------------------------- | --------- | ------------------------------------------------------------ | | **PUBLIC_SDK_KEY** | 必須 | Adapty のアプリ設定にある **Public SDK key** フィールドで確認できるキーです: [**App settings** -> **General** タブ -> **API keys** セクション](https://app.adapty.io/settings/general) | | **withLogLevel** | 任意 | Adapty はエラーやその他の重要な情報をログに記録し、アプリの動作状況を把握できるようにします。利用可能なレベルは以下のとおりです。
  • error: エラーのみがログに記録されます。
  • warn: エラーと、重大なエラーではないが注意が必要な SDK からのメッセージがログに記録されます。
  • info: エラー、警告、および各モジュールのライフサイクルなどの重要な情報メッセージがログに記録されます。
  • verbose: 関数呼び出し、API クエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます。
| | **withObserverMode** | 任意 |

[オブザーバーモード](observer-vs-full-mode)を制御する真偽値です。購入とサブスクリプションの状態を自分で管理し、サブスクリプションイベントの送信と分析に Adapty を使用する場合は有効にしてください。

デフォルト値は `false` です。

🚧 オブザーバーモードで動作している場合、Adapty SDK はトランザクションをクローズしないため、自前で処理する必要があります。

| | **withCustomerUserId** | 任意 | 自社システムにおけるユーザーの識別子です。サブスクリプションおよび分析イベントに含めて送信し、イベントを正しいプロファイルに紐付けます。[**Profiles and Segments**](https://app.adapty.io/profiles/users) メニューで `customerUserId` によるユーザー検索も可能です。 | | **withIdfaCollectionDisabled** | 任意 |

IDFA の収集と共有を無効にするには `true` を設定します。

ユーザーの IP アドレス共有も無効になります。

デフォルト値は `false` です。

IDFA 収集の詳細については、[Analytics integration](analytics-integration#disable-collection-of-advertising-identifiers) セクションをご参照ください。

| | **withIpAddressCollectionDisabled** | 任意 |

ユーザーの IP アドレスの収集と共有を無効にするには `true` を設定します。

デフォルト値は `false` です。

| ### Adapty SDK の AdaptyUI モジュールをアクティベートする \{#activate-adaptyu-module-of-adapty-sdk\} AdaptyUI モジュールの設定が必要なのは、[ペイウォールビルダー](adapty-paywall-builder)を使用する予定がある場合のみです。 ```dart showLineNumbers title="Dart" try { final mediaCache = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 100 * 1024 * 1024, // 100MB memoryStorageCountLimit: 2147483647, // 2^31 - 1, max int value in Dart diskStorageSizeLimit: 100 * 1024 * 1024, // 100MB ); await AdaptyUI().activate( configuration: AdaptyUIConfiguration(mediaCache: mediaCache), observer: , ); } catch (e) { // handle the error } ``` AdaptyUI の設定はオプションであり、設定なしで AdaptyUI モジュールをアクティベートすることも可能です。ただし、設定を使用する場合はすべてのパラメータが必須となります。 パラメータ: | パラメータ | 必須/任意 | 説明 | | :------------------------------ | :-------- | :----------------------------------------------------------- | | **memoryStorageTotalCostLimit** | 必須 | ストレージの合計コスト上限(バイト単位)。 | | **memoryStorageCountLimit** | 必須 | メモリストレージのアイテム数上限。 | | **diskStorageSizeLimit** | 必須 | ディスク上のストレージファイルサイズ上限(バイト単位)。0 は上限なしを意味します。 | --- # End of Documentation _Generated on: 2026-07-01T16:29:19.418Z_ _Successfully processed: 42/42 files_