---
title: "Migrer le SDK Flutter Adapty vers v4.0"
description: "Migrez vers le SDK Flutter Adapty v4.0 en remplaçant les API paywall par des API flow, compatibles avec le Flow Builder et le Paywall Builder."
---

Le SDK Flutter Adapty 4.0 introduit les flows et renomme les API paywall en conséquence. Les nouvelles API fonctionnent aussi bien avec le nouveau Flow Builder qu'avec le Paywall Builder existant — aucune modification de configuration n'est requise côté Adapty Dashboard.

## Référence rapide \{#quick-reference\}

| v3 | v4 |
|---|---|
| `Adapty().getPaywall(placementId: id)` | `Adapty().getFlow(placementId: id)` |
| `Adapty().getPaywallForDefaultAudience(placementId: id)` | `Adapty().getFlowForDefaultAudience(placementId: id)` |
| `Adapty().getPaywallProducts(paywall: paywall)` | `Adapty().getPaywallProducts(flow: flow)` |
| `Adapty().logShowPaywall(paywall: paywall)` | `Adapty().logShowFlow(flow: flow)` |
| `AdaptyPaywall` (type) | `AdaptyFlow` |
| `AdaptyPaywallFetchPolicy` (type) | `AdaptyFlowFetchPolicy` |
| `AdaptyUI().createPaywallView(paywall: paywall)` | `AdaptyUI().createFlowView(flow: flow)` |
| `AdaptyUIPaywallView` (type) | `AdaptyUIFlowView` |
| `AdaptyUIPaywallPlatformView` (widget) | `AdaptyUIFlowPlatformView` |
| `AdaptyUI().presentPaywallView(view)` / `dismissPaywallView(view)` | `AdaptyUI().presentFlowView(view)` / `dismissFlowView(view)` |
| `AdaptyUIPaywallsEventsObserver` | `AdaptyUIFlowsEventsObserver` |
| `AdaptyUI().setPaywallsEventsObserver(observer)` | `AdaptyUI().setFlowsEventsObserver(observer)` |
| `paywallViewDid*` callbacks | `flowViewDid*` callbacks |
| `paywallViewDidFailRendering` | `flowViewDidReceiveError` |

`AdaptyPaywallProduct` conserve son nom — les produits appartiennent toujours à un flow, et `getPaywallProducts` prend désormais un `AdaptyFlow`. Vous ne passez plus de `locale` lors de la récupération d'un flow. Les API d'achat et de profil (`makePurchase`, `restorePurchases`, `getProfile`, `identify`, etc.) sont inchangées, tout comme les méthodes de vue `present`, `dismiss` et `showDialog`. Certains comportements par défaut ont changé — voir [Changements des comportements par défaut](#default-behavior-changes).

## Versions minimales \{#minimum-versions\}

Adapty Flutter SDK 4.0 relève les exigences minimales :

- **iOS 15.0** — cible de déploiement iOS minimale, relevée depuis iOS 13.0.
- **Xcode 26** ou version ultérieure — le SDK iOS natif utilise Swift tools 6.2.
- **Flutter 3.32.0** (Dart 3.8.0) ou version ultérieure.

## Installation \{#installation\}

### Mettre à jour le package \{#update-the-package\}

Le package à installer dépend de si votre application utilise le mode enfant.

Pour la plupart des applications, mettez à jour `adapty_flutter` vers la v4.0 dans votre `pubspec.yaml` :

```yaml showLineNumbers title="pubspec.yaml"
dependencies:
  adapty_flutter: 4.0.3
```

Si votre application utilise le mode enfant, spécifiez `adapty_flutter_kids` à la place :

```yaml showLineNumbers title="pubspec.yaml"
dependencies:
  adapty_flutter_kids: 4.0.3
```

Ce **package autonome** supprime le code IDFA et de suivi publicitaire pour se conformer aux exigences de l'App Store. Mettez à jour le chemin d'import Dart vers `package:adapty_flutter_kids/adapty_flutter.dart`. Pour le reste, la migration est exactement la même que pour le package standard.

Le mode Kids requiert également de désactiver la collecte d'adresses IP dans l'Adapty Dashboard — consultez [Kids Mode](kids-mode-flutter) pour la configuration complète.

### iOS : les SDK natifs passent désormais par Swift Package Manager

[Le dépôt de specs CocoaPods passe en lecture seule en décembre 2026](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), aussi à partir de la v4 le SDK iOS natif **n'est plus distribué via CocoaPods** — le plugin le récupère uniquement via **Swift Package Manager**.

Si vous utilisez Flutter 3.32–3.43, activez le support de Swift Package Manager une seule fois :

```bash
flutter config --enable-swift-package-manager
```

Flutter 3.44 et versions ultérieures activent Swift Package Manager par défaut, aucune action n'est donc nécessaire.

## Récupérer des flows \{#fetching-flows\}

### getPaywall → getFlow

Le type retourné passe de `AdaptyPaywall` à `AdaptyFlow`, et il n'est plus nécessaire de passer un `locale` — lorsque vous affichez un flow, la localisation est résolue automatiquement ; pour les paywalls personnalisés, toutes les locales configurées sont retournées dans `flow.remoteConfigs` :

```diff showLineNumbers
- final paywall = await Adapty().getPaywall(placementId: 'YOUR_PLACEMENT_ID', locale: 'en');
+ final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID');
```

`getPaywallForDefaultAudience` est renommé de la même manière :

```diff showLineNumbers
- final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID', locale: 'en');
+ final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID');
```

Le type de politique de récupération est renommé de `AdaptyPaywallFetchPolicy` en `AdaptyFlowFetchPolicy` ; ses options (`reloadRevalidatingCacheData`, `returnCacheDataElseLoad`, `returnCacheDataIfNotExpiredElseLoad`) restent inchangées.

### getPaywallProducts(paywall) → getPaywallProducts(flow)

`getPaywallProducts` garde son nom mais prend désormais un `AdaptyFlow` via le paramètre `flow` :

```diff showLineNumbers
- final products = await Adapty().getPaywallProducts(paywall: paywall);
+ final products = await Adapty().getPaywallProducts(flow: flow);
```

### Fichiers de secours \{#fallback-files\}

Le format des fichiers de secours [a changé avec le SDK v4](fallback-flows). Téléchargez le nouveau fichier depuis **[Placements](https://app.adapty.io/placements)** > **Fallbacks** et intégrez-le dans votre application.

## Modèle de données \{#data-model\}

`getFlow` renvoie un `AdaptyFlow` au lieu d'un `AdaptyPaywall`, et la structure de l'objet a changé :

| Membre v3 `AdaptyPaywall` | Membre v4 `AdaptyFlow` | Action |
|---|---|---|
| `remoteConfig` (unique, nullable) | `remoteConfigs` (liste) | Un flow contient un Remote Config par langue configurée. Le getter `remoteConfig` existe toujours et renvoie la première entrée ; pour choisir une langue spécifique, cherchez dans `remoteConfigs` par son `locale`. |
| `productIdentifiers` | `productIdentifiers` | Conservé, mais désormais collecté pour toutes les variations de paywall du flow. Les identifiants par variation se trouvent sur `flow.paywalls[i].productIdentifiers`. |
| `hasViewConfiguration` | `hasViewConfiguration` | Inchangé. |
| `placementId` (déprécié) | supprimé | Utilisez `flow.placement.id`. |
| `revision` (déprécié) | supprimé | Utilisez `flow.placement.revision`. |
| `vendorProductIds` (déprécié) | supprimé | Utilisez `productIdentifiers`. |
| _(nouveau)_ | `paywalls` (liste de `AdaptyFlowPaywall`) | Chaque entrée est une variation de paywall dans le flow, avec son propre `name`, `variationId` et `productIdentifiers`. |

`AdaptyPaywallViewConfiguration` n'est plus exposé — la configuration de vue est désormais opaque. Supprimez toute référence à ce type.

## Méthodes de paywall web \{#web-paywall-methods\}

`openWebPaywall` et `createWebPaywallUrl` conservent leurs noms, mais le paramètre `paywall` attend désormais un `AdaptyFlowPaywall` (une variante de flow) au lieu d'un `AdaptyPaywall`. Vous pouvez toujours passer un `AdaptyPaywallProduct` à la place.

```diff showLineNumbers
  final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID');
- await Adapty().openWebPaywall(paywall: paywall);
+ if (flow.paywalls.isNotEmpty) {
+   await Adapty().openWebPaywall(paywall: flow.paywalls[0]);
+ }
```

## Suivi des vues de flow \{#tracking-flow-views\}

### logShowPaywall → logShowFlow

`logShowPaywall` est renommé en `logShowFlow` et accepte désormais un `AdaptyFlow`. L'événement est toujours enregistré pour la même variation, donc les métriques de funnel et de test A/B existantes continuent de fonctionner sans modifications du tableau de bord.

```diff showLineNumbers
- await Adapty().logShowPaywall(paywall: paywall);
+ await Adapty().logShowFlow(flow: flow);
```

Comme dans la v3, vous n'avez pas besoin d'appeler cette méthode lors de l'affichage de flows ou de paywalls créés avec le [Flow Builder](adapty-flow-builder) ou le [Paywall Builder](adapty-paywall-builder) — Adapty suit ces vues automatiquement.

## Affichage des flows \{#displaying-flows\}

### createPaywallView → createFlowView

Renommez la méthode et passez l'`AdaptyFlow` via le paramètre `flow`. Les autres paramètres (`loadTimeout`, `preloadProducts`, `customTags`, `customTimers`, `customAssets`, `productPurchaseParams`) restent inchangés, ainsi que les méthodes de la vue `present`, `dismiss` et `showDialog` :

```diff showLineNumbers
- final view = await AdaptyUI().createPaywallView(paywall: paywall);
+ final view = await AdaptyUI().createFlowView(flow: flow);
  await view.present();
```

### AdaptyUIPaywallView → AdaptyUIFlowView

Le type de vue est renommé. Sa propriété `paywallVariationId` (dépréciée) est supprimée — utilisez `variationId` :

```diff showLineNumbers
- void flowViewDidAppear(AdaptyUIPaywallView view) {
+ void flowViewDidAppear(AdaptyUIFlowView view) {
```

### AdaptyUIPaywallPlatformView → AdaptyUIFlowPlatformView

Si vous intégrez la vue en tant que widget dans votre arbre de widgets, renommez-la et passez le paramètre `flow`. Les callbacks d'événements (`onDidAppear`, `onDidFinishPurchase`, etc.) conservent leurs noms :

```diff showLineNumbers
- AdaptyUIPaywallPlatformView(
-   paywall: paywall,
+ AdaptyUIFlowPlatformView(
+   flow: flow,
    onDidFinishPurchase: (view, product, purchaseResult) { /* … */ },
  )
```

:::note
Une vue de flow créée avec `createFlowView` est à usage unique : après avoir appelé `dismiss()`, la vue est libérée de la mémoire et ne peut plus être présentée de nouveau — appelez `createFlowView` à nouveau pour afficher le flow une nouvelle fois.
:::

## Gestion des événements \{#handling-events\}

La classe d'observateur est renommée de `AdaptyUIPaywallsEventsObserver` en `AdaptyUIFlowsEventsObserver`, sa méthode d'enregistrement de `setPaywallsEventsObserver` en `setFlowsEventsObserver`, et tous les callbacks `paywallViewDid*` en `flowViewDid*` :

```diff showLineNumbers
- class MyObserver extends AdaptyUIPaywallsEventsObserver {
+ class MyObserver extends AdaptyUIFlowsEventsObserver {
    @override
-   void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) {
+   void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) {
      // …
    }
  }

- AdaptyUI().setPaywallsEventsObserver(this);
+ AdaptyUI().setFlowsEventsObserver(this);
```

Trois callbacks sont désormais **obligatoires** — votre observateur ne compilera pas sans eux :

- **`flowViewDidFinishPurchase`**: Était optionnel en v3, où le comportement par défaut fermait la vue après un achat. Vous décidez maintenant de la suite : continuer le flow ou appeler `view.dismiss()`.
- **`flowViewDidFinishRestore`**: Obligatoire, comme en v3.
- **`flowViewDidReceiveError`**: Remplace `paywallViewDidFailRendering` et reçoit désormais aussi les autres erreurs de vue.

Deux changements mineurs :

- `setFlowsEventsObserver` (et `setOnboardingsEventsObserver`) acceptent désormais `null` pour détacher un observateur précédemment défini, afin que le SDK ne le conserve plus.
- Le nouveau callback optionnel `flowViewDidReceiveAnalyticEvent` est réservé aux événements analytiques personnalisés provenant d'un flow. Les flows n'émettent pas encore ces événements vers votre code, vous n'avez donc pas besoin de l'implémenter.

v4 ajoute également des fonctionnalités que vous pouvez activer à la demande :

- `AdaptyUI().setObserverModeResolver(...)` avec un `AdaptyUIObserverModeResolver` — gère les achats et restaurations initiés depuis les flows lorsque le SDK s'exécute en [mode Observateur](implement-observer-mode-flutter). Auparavant, cette fonctionnalité n'était disponible que dans les SDK natifs iOS et Android. Voir [Présenter les flows en mode Observateur](flutter-present-flows-in-observer-mode).
- `AdaptyUI().setSystemRequestsHandler(...)` avec un `AdaptyUISystemRequestsHandler` — réservé aux requêtes système provenant d'un flow (demandes de permissions OS et demandes d'avis App Store). Les flows ne déclenchent pas encore ces requêtes, vous n'avez donc pas besoin d'enregistrer un handler.

## API supprimées \{#removed-apis\}

Ces symboles étaient dépréciés dans la version 3.x et sont supprimés dans la v4 :

### setFallbackPaywalls → setFallback

```diff showLineNumbers
- await Adapty().setFallbackPaywalls(assetId);
+ await Adapty().setFallback(assetId);
```

### withIdfaCollectionDisabled → withAppleIdfaCollectionDisabled

```diff showLineNumbers
  configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY')
-   ..withIdfaCollectionDisabled(true),
+   ..withAppleIdfaCollectionDisabled(true),
```

### Autres membres supprimés

- **`AdaptyPurchaseResultSuccess.jwsTransaction`** : Utilisez `appleJwsTransaction`.
- **`AdaptyUIFlowView.paywallVariationId`** : Utilisez `variationId`.
- **`AdaptyUIObserver` et `AdaptyUI().setObserver(...)`** : Utilisez `AdaptyUIFlowsEventsObserver` et `setFlowsEventsObserver(...)`.

## Changements de comportement par défaut \{#default-behavior-changes\}

Ces changements n'entraînent pas d'erreurs de compilation ; testez-les donc au moment de l'exécution :

- **Achat réussi** : En v3, le `paywallViewDidFinishPurchase` par défaut fermait la vue. En v4, `flowViewDidFinishPurchase` est obligatoire et n'a pas de comportement par défaut — fermez la vue vous-même si c'est ce que vous souhaitez.
- **Bouton retour système Android** : Il ne ferme plus un flow par défaut. L'action est transmise à `flowViewDidPerformAction` sous la forme `AndroidSystemBackAction` — gérez-la là si vous voulez que le bouton retour ferme le flow.
- **Ouverture d'URL** : Le `flowViewDidPerformAction` par défaut gère désormais `OpenUrlAction` en ouvrant l'URL nativement (en respectant le paramètre navigateur intégré ou externe du tableau de bord), en plus de fermer la vue sur `CloseAction`. Surchargez le callback pour gérer les URL vous-même.
- **Erreurs de vue** : `flowViewDidReceiveError` est obligatoire, et la fermeture dépend de votre implémentation. Si votre intégration v3 reposait sur la fermeture automatique de la vue en cas d'erreur de rendu, appelez `view.dismiss()` dans ce callback.
- **Cycle de vie de la vue** : Fermer une vue de flow ou d'onboarding la libère de la mémoire. Une vue fermée ne peut plus être réaffichée — créez-en une nouvelle à la place.

## Dépréciation de l'API onboarding \{#onboarding-api-deprecation\}

L'API onboarding héritée est dépréciée depuis la v4.0 au profit du [Flow Builder](adapty-flow-builder). Elle fonctionne toujours, et votre IDE signale les symboles dépréciés via leurs annotations `@Deprecated` — aucun avertissement n'est émis à l'exécution. Ces symboles seront supprimés dans une prochaine version, pensez donc à migrer vos onboardings vers le Flow Builder.

Symboles dépréciés : `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView`, `presentOnboardingView`, `dismissOnboardingView`, `setOnboardingsEventsObserver`, `AdaptyOnboarding`, `AdaptyUIOnboardingView`, `AdaptyUIOnboardingPlatformView`, `AdaptyUIOnboardingsEventsObserver`, ainsi que les modèles d'état, de saisie et d'analytique d'onboarding.