Migrer le SDK Adapty Kotlin Multiplatform vers v4.1
Le SDK Adapty Kotlin Multiplatform 4.1 est la première version stable de la ligne 4.x — la 4.0 n’a été publiée qu’en bêta, donc si vous êtes sur la 3.x, migrez directement vers la 4.1. Ce guide couvre l’ensemble de la migration : les flows introduits en 4.0 et les changements apportés en 4.1.
La version 4.x introduit les flows et renomme les API paywall en conséquence. Les nouvelles API fonctionnent à la fois avec le Flow & Paywall Builder et l’ancien Paywall Builder — aucune modification de configuration n’est requise côté Adapty Dashboard. De plus, la version 4.1 rend l’attribution Adapty opt-in, renomme les API d’attribution externe et le type d’abonnement produit, et ajoute les achats intégrés promus sur l’App Store.
Vous venez de la bêta 4.0 ? Mettez à jour la version, puis seules cinq sections s’appliquent : L’attribution Adapty est désactivée par défaut, les API d’attribution externe renommées, AdaptyPaywallProductSubscription → AdaptyProductSubscription, les achats intégrés mis en avant sur l’App Store et choisir une mise en page spécifique. hasViewConfiguration est également de retour dans le modèle de flow.
Référence rapide
| v3 | v4.1 |
|---|---|
| Attribution Adapty activée automatiquement | désactivée par défaut — à activer avec .withAdaptyAttributionEnabled(true) |
Adapty.getPaywall(placementId, locale) | Adapty.getFlow(placementId) |
Adapty.getPaywallForDefaultAudience(placementId, locale) | Adapty.getFlowForDefaultAudience(placementId) |
Adapty.getPaywallProducts(paywall) | Adapty.getPaywallProducts(flow) |
Adapty.logShowPaywall(paywall) | Adapty.logShowFlow(flow) |
AdaptyPaywall | AdaptyFlow |
AdaptyUI.createPaywallView(paywall, ...) | AdaptyUI.createFlowView(flow, ...) |
AdaptyUI.createNativePaywallView(...) → AdaptyNativePaywallView | AdaptyUI.createNativeFlowView(...) → AdaptyNativeFlowView |
AdaptyUIPaywallView | AdaptyUIFlowView |
AdaptyUI.presentPaywallView(view) / dismissPaywallView(view) | AdaptyUI.presentFlowView(view) / dismissFlowView(view) |
AdaptyUI.setPaywallsEventsObserver(observer) | AdaptyUI.setFlowsEventsObserver(observer) |
AdaptyUI.registerPaywallEventsListener / unregisterPaywallEventsListener | AdaptyUI.registerFlowEventsListener / unregisterFlowEventsListener |
AdaptyUIPaywallsEventsObserver | AdaptyUIFlowsEventsObserver |
AdaptyUIPaywallPlatformView(paywall, ...) | AdaptyUIFlowPlatformView(flow, ...) |
paywallViewDidPerformAction, paywallViewDidAppear et autres callbacks paywallView... | flowViewDidPerformAction, flowViewDidAppear et autres callbacks flowView... |
paywallViewDidFailRendering | flowViewDidReceiveError |
Adapty.updateAttribution(attribution, source) avec une source de type String | Adapty.updateExternalAttribution(attribution, provider) avec un AdaptyExternalAttributionProvider |
fournisseur passé sous forme de chaîne, par exemple "adjust" | AdaptyExternalAttributionProvider, par exemple AdaptyExternalAttributionProvider.ADJUST |
AdaptyProfile.appliedAttributionSources: List<String> | AdaptyProfile.appliedExternalAttributionProviders: List<AdaptyExternalAttributionProvider> |
AdaptyPaywallProductSubscription | AdaptyProductSubscription |
| Achats intégrés promus finalisés automatiquement, sans possibilité de les intercepter | OnPromotedPurchaseListener et Adapty.makePromotedPurchase(product) délèguent la finalisation à votre application |
AdaptyPaywallProduct conserve son nom — les produits appartiennent toujours à un flow, et getPaywallProducts conserve également son nom, en prenant désormais un AdaptyFlow. Les méthodes getFlow et getFlowForDefaultAudience n’acceptent plus de paramètre locale — passez-le plutôt à createFlowView. Les APIs d’achat et de profil (makePurchase, restorePurchases, getProfile, identify, updateProfile) ainsi que setFallback conservent les mêmes signatures, mais le fichier de secours lui-même doit être retéléchargé — voir Fichiers de secours. Les méthodes d’onboarding fonctionnent toujours mais sont dépréciées — voir Dépréciation de l’API d’onboarding. Certains comportements par défaut ont changé — voir Changements de comportement par défaut.
Installation
Mettez à jour la version et synchronisez le projet :
[versions]
adapty-kmp = "<the latest SDK version>"
[libraries]
adapty-kmp = { module = "io.adapty:adapty-kmp", version.ref = "adapty-kmp" }
adapty-kmp-ui = { module = "io.adapty:adapty-kmp-ui", version.ref = "adapty-kmp" }
Le module adapty-kmp-ui n’est nécessaire que si vous affichez des flows et des paywalls via la couche Compose Multiplatform (view.present()). Consultez Installer le SDK Adapty pour la configuration complète.
Les SDK Adapty natifs sous-jacents sont mis à jour vers leurs versions 4.x sur les deux plateformes et sont résolus automatiquement — aucune modification de build n’est nécessaire. La cible de déploiement iOS reste 15.0, inchangée par cette version.
⚠️ L’attribution Adapty est désactivée par défaut
Si vous utilisez l’attribution Adapty et mettez à jour vers le SDK 4.1 sans l’activer explicitement, tout se casse silencieusement — les installations cessent d’être enregistrées, sans aucun avertissement.
Dans les versions antérieures, le SDK enregistrait les installations pour Adapty Attribution automatiquement. À partir de la version 4.1 du SDK, cette fonctionnalité est désactivée par défaut : le SDK n’enregistre pas les installations, le listener défini avec setOnInstallationDetailsListener ne se déclenche jamais, et getCurrentInstallationStatus renvoie AdaptyInstallationStatus.Determined.NotAvailable.
Si vous utilisez Adapty Attribution, activez-la lors de l’activation du SDK :
val config = AdaptyConfig
.Builder("PUBLIC_SDK_KEY")
+ .withAdaptyAttributionEnabled(true)
.build()
Adapty.activate(configuration = config)
Si vous n’utilisez pas Adapty Attribution, aucune modification n’est nécessaire.
Récupération des flows
getPaywall → getFlow
Le type retourné passe de AdaptyPaywall à AdaptyFlow, et le paramètre locale se déplace de l’appel de récupération vers createFlowView ; pour les paywalls personnalisés, toutes les locales sont retournées dans flow.remoteConfigs :
- Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en")
- .onSuccess { paywall ->
- // use the paywall
+ Adapty.getFlow("YOUR_PLACEMENT_ID")
+ .onSuccess { flow ->
+ AdaptyUI.createFlowView(flow = flow, locale = "en")
}
.onError { error ->
// handle the error
}
locale reste optionnel sur createFlowView : omettez-le et la vue s’affiche en en, ou dans la localisation par défaut du flow si celui-ci ne possède pas de version en. Voir Localisations et codes de langue.
getPaywallForDefaultAudience est renommé de la même façon :
- Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en")
+ Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID")
getPaywallProducts(paywall) → getPaywallProducts(flow)
getPaywallProducts conserve son nom mais prend désormais un AdaptyFlow :
- Adapty.getPaywallProducts(paywall)
+ Adapty.getPaywallProducts(flow)
.onSuccess { products ->
// use the products
}
Fichiers de secours
Le format du fichier de secours a changé dans le SDK v4. Téléchargez le nouveau fichier depuis Placements > Fallbacks et intégrez-le à votre application.
Modèle de données
getFlow renvoie un AdaptyFlow à la place d’un AdaptyPaywall, et la structure de l’objet a changé :
Propriété v3 AdaptyPaywall | Propriété v4 AdaptyFlow | Action |
|---|---|---|
remoteConfig: AdaptyRemoteConfig? (unique) | remoteConfigs: List<AdaptyRemoteConfig> | Un flow contient un Remote Config par langue configurée. Lisez celui qui correspond à l’utilisateur : flow.remoteConfigs.firstOrNull { it.locale == "en" }. |
| (nouveau) | paywalls: List<AdaptyFlowPaywall> | Chaque entrée est une variation de paywall dans le flow, avec ses propres name, variationId et productIdentifiers. Les méthodes de paywall web prennent un AdaptyFlowPaywall — voir Méthodes de paywall web. |
productIdentifiers | déplacé | Les identifiants de produit se trouvent désormais sur chaque variation : flow.paywalls[i].productIdentifiers. Pour récupérer les produits, continuez d’appeler getPaywallProducts(flow). |
hasViewConfiguration | conservé | Indique si le flow embarque une mise en page qu’AdaptyUI peut afficher. Cette propriété était absente dans la bêta 4.0 et est de retour en 4.1 — si vous aviez supprimé vos vérifications pour la bêta, vous pouvez l’utiliser à nouveau. false signifie que le flow ne contient aucune mise en page : traitez-le alors comme Remote Config uniquement. Vous pouvez aussi appeler createFlowView et gérer l’erreur (voir Affichage des flows). |
hasViewConfiguration est également présent sur AdaptyOnboarding, inchangé.
Méthodes de paywall web
openWebPaywall et createWebPaywallUrl conservent leurs noms, mais le paramètre paywall est remplacé par un paramètre flowPaywall qui prend un AdaptyFlowPaywall — l’une des variantes dans flow.paywalls. Vous pouvez toujours passer un AdaptyPaywallProduct à la place :
- Adapty.openWebPaywall(paywall = paywall)
+ flow.paywalls.firstOrNull()?.let { flowPaywall ->
+ Adapty.openWebPaywall(flowPaywall = flowPaywall)
+ }
Suivi des vues de flow
logShowPaywall → logShowFlow
logShowPaywall est renommé en logShowFlow et prend désormais un AdaptyFlow. L’événement est toujours enregistré pour la même variation, de sorte que les métriques de funnel et de test A/B existantes continuent de fonctionner sans modification du tableau de bord.
- Adapty.logShowPaywall(paywall)
+ Adapty.logShowFlow(flow)
Comme dans la v3, vous n’avez pas besoin d’appeler cette méthode lors de l’affichage des flows ou paywalls rendus par Adapty — Adapty suit automatiquement ces vues.
Affichage des flows
createPaywallView → createFlowView
Renommez la méthode factory et transmettez l’AdaptyFlow. Le type de vue renvoyé est renommé de AdaptyUIPaywallView en AdaptyUIFlowView, mais ses méthodes (present, dismiss) et les paramètres optionnels (loadTimeout, preloadProducts, customTags, customTimers, customAssets, productPurchaseParams) restent inchangés. Un paramètre optionnel est nouveau : locale, qui remplace le locale que vous passiez auparavant à getPaywall — voir Récupérer les flows.
customTimers existe toujours, mais il n’affecte que les paywalls du Paywall Builder hérité. Le minuteur de décompte d’un flow fonctionne selon le comportement défini dans le Flow & Paywall Builder, donc un flow ignore ce que vous passez ici.
- AdaptyUI.createPaywallView(paywall)
+ AdaptyUI.createFlowView(flow)
.onSuccess { view ->
view.present()
}
.onError { error ->
// handle the error
}
Si vous n’utilisez pas Compose Multiplatform, la méthode factory native est renommée de la même façon :
- AdaptyUI.createNativePaywallView(paywall)
+ AdaptyUI.createNativeFlowView(flow)
createFlowView retourne une AdaptyResult.Error si le flow n’a pas de vue configurée, vous pouvez donc supprimer la vérification hasViewConfiguration de la v3 et gérer l’erreur à la place :
- if (paywall.hasViewConfiguration) {
- AdaptyUI.createPaywallView(paywall)
- .onSuccess { view -> view.present() }
- }
+ AdaptyUI.createFlowView(flow)
+ .onSuccess { view -> view.present() }
+ .onError { error ->
+ // the flow has no view configured, or view creation failed
+ }
Une vue de flow est à usage unique : après avoir appelé dismiss(), la vue est détruite. Appelez à nouveau createFlowView pour afficher le flow une nouvelle fois.
Gestion des événements
L’observateur d’événements est renommé de AdaptyUIPaywallsEventsObserver en AdaptyUIFlowsEventsObserver, et ses callbacks remplacent le préfixe paywallView par flowView. Le contenu des handlers existants n’a pas besoin d’être modifié — il suffit de renommer le type et les overrides :
- AdaptyUI.setPaywallsEventsObserver(object : AdaptyUIPaywallsEventsObserver {
- override fun paywallViewDidFinishPurchase(
- view: AdaptyUIPaywallView,
+ AdaptyUI.setFlowsEventsObserver(object : AdaptyUIFlowsEventsObserver {
+ override fun flowViewDidFinishPurchase(
+ view: AdaptyUIFlowView,
product: AdaptyPaywallProduct,
purchaseResult: AdaptyPurchaseResult
) {
// custom logic after purchase
}
})
Un callback est également renommé : paywallViewDidFailRendering devient flowViewDidReceiveError. Il se déclenche pour les mêmes erreurs de rendu qu’auparavant, ainsi que pour d’autres erreurs d’exécution non liées aux achats :
- override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) {}
+ override fun flowViewDidReceiveError(view: AdaptyUIFlowView, error: AdaptyError) {}
Consultez Gérer les événements flow et paywall pour la liste complète des callbacks.
Vue de la plateforme Compose
Si vous intégrez des vues avec le composable Compose Multiplatform, AdaptyUIPaywallPlatformView(paywall, ...) est renommé en AdaptyUIFlowPlatformView(flow, ...). Les callbacks d’événements conservent leurs noms onDid..., sauf onDidFailRendering, qui devient onDidReceiveError :
- AdaptyUIPaywallPlatformView(
- paywall = paywall,
+ AdaptyUIFlowPlatformView(
+ flow = flow,
onDidFinishPurchase = { view, product, result -> /* ... */ },
)
Comme dans la v3, les callbacks que vous passez ici (et tout observateur enregistré via registerFlowEventsListener) s’exécutent en plus de l’observateur global, et non à sa place — votre callback observe un événement ; il ne remplace pas le comportement global par défaut. Gardez les valeurs par défaut modifiées à l’esprit : par exemple, le comportement global par défaut ne ferme plus la vue après un achat.
Nouvelles API
AdaptyUI.setObserverModeResolver(...)avec unAdaptyUIObserverModeResolver— gérez les achats et restaurations initiés depuis des flows lorsque le SDK fonctionne en mode Observer. Auparavant, cette fonctionnalité n’était disponible que dans les SDKs natifs iOS et Android. Voir Présenter des flows en mode Observer.AdaptyUI.setSystemRequestsHandler(...)avec unAdaptyUISystemRequestsHandler— réservé aux requêtes système émises par un flow (demandes de permissions OS et requêtes d’évaluation de l’app). Les flows ne déclenchent pas encore ces requêtes, vous n’avez donc pas besoin d’enregistrer un handler.- Le nouveau callback optionnel
flowViewDidReceiveAnalyticEventremonte les événements analytiques d’un flow, en commençant par une vue d’écran pour chaque écran qu’un utilisateur ouvre. Voir Suivre les vues d’écran des flows. AdaptyUI.openWebUrl(url, openIn)etAdaptyUI.requestAppReview()— ces méthodes alimentent la gestion par défaut deOpenUrlActionet le comportement par défaut dehandleAppReviewRequest, de sorte que les URLs et les demandes d’évaluation de l’app sont traitées nativement sans configuration supplémentaire. Appelez-les directement uniquement si vous surchargez ces comportements par défaut.AdaptyUIFlowView.locale— indique la localisation avec laquelle la vue a été construite, ce qui vous permet de savoir laquelle l’utilisateur voit réellement.AdaptyConfig.ServerCluster.CN— une nouvelle option de cluster serveur aux côtés deDEFAULTetEU, pour connecter votre application aux serveurs Adapty en Chine.
APIs d’attribution externe renommées
À partir de la version 4.1 du SDK, les APIs qui transmettent les données d’attribution depuis un fournisseur externe (Adjust, AppsFlyer, Branch, Tenjin, Apple Ads ou un fournisseur personnalisé) ont été renommées pour correspondre aux SDKs natifs, et le fournisseur passe d’une chaîne de caractères à un type. Il n’existe pas d’alias dépréciés, donc les appels existants cessent de compiler jusqu’à ce que vous les mettiez à jour.
updateAttribution → updateExternalAttribution
La méthode est renommée, son paramètre source devient provider, et ce paramètre accepte désormais un AdaptyExternalAttributionProvider plutôt qu’une String :
- Adapty.updateAttribution(attribution, "adjust")
+ Adapty.updateExternalAttribution(attribution, AdaptyExternalAttributionProvider.ADJUST)
Les données d’attribution restent un Map<String, Any>.
L’appel retourne une fois que le backend a accepté les données pour un traitement asynchrone. Un résultat positif ne signifie pas que les données ont déjà été appliquées au profil.
AdaptyExternalAttributionProvider
Le fournisseur est désormais un type avec des valeurs prédéfinies : APPLE_ADS, ADJUST, APPSFLYER, BRANCH, TENJIN et CUSTOM. Pour tout autre fournisseur, construisez-en un à partir de son identifiant :
AdaptyExternalAttributionProvider("your_provider")
La construction directe couvre également les fournisseurs qu’Adapty ajoutera après cette version du SDK — l’identifiant est transmis tel quel au backend, sans être réduit à une valeur inconnue. Les espaces en début et fin de chaîne sont supprimés.
Chaque valeur prédéfinie correspond à l’identifiant que vous avez passé à updateAttribution auparavant : AdaptyExternalAttributionProvider.APPLE_ADS.value vaut apple_search_ads, et les autres correspondent à leurs propres noms en minuscules.
AdaptyProfile.appliedAttributionSources → appliedExternalAttributionProviders
La propriété du profil qui liste les fournisseurs d’attribution appliqués au profil est renommée, et le type de ses éléments change en conséquence :
- if (profile.appliedAttributionSources.contains("apple_search_ads")) {
+ if (profile.appliedExternalAttributionProviders.contains(AdaptyExternalAttributionProvider.APPLE_ADS)) {
// Apple Ads attribution has been applied
}
AdaptyPaywallProductSubscription → AdaptyProductSubscription
Le type des détails d’abonnement est renommé, car les produits mis en avant utilisent désormais le même type. Seul le nom change — chaque propriété conserve son nom et son type :
- val subscription: AdaptyPaywallProductSubscription? = product.subscription
+ val subscription: AdaptyProductSubscription? = product.subscription
Achats intégrés mis en avant sur l’App Store
Le SDK 4.1 achemine les achats intégrés mis en avant sur votre page produit App Store jusqu’à votre app sur iOS. Les versions précédentes finalisaient ce type d’achat automatiquement, sans laisser à votre app la moindre possibilité de l’intercepter. À partir de la version 4.1, l’achat attend votre code pour s’exécuter — une action est donc nécessaire, même si vous n’avez jamais utilisé les achats mis en avant.
Pour prendre en charge les achats promus, enregistrez un OnPromotedPurchaseListener et finalisez l’achat en passant le produit à Adapty.makePromotedPurchase. Sans listener enregistré, l’achat est mis en attente sans être finalisé : l’utilisateur appuie sur Buy sur votre page App Store, mais rien ne se passe dans votre application. Enregistrez le listener le plus tôt possible — consultez Achats intégrés depuis l’App Store pour les détails de timing et un exemple complet.
Choisir une mise en page spécifique
createFlowView, createNativeFlowView et AdaptyUIFlowPlatformView acceptent un nouveau paramètre optionnel customLayoutId. Passez-le pour afficher une mise en page spécifique dans la configuration des mises en page du flow, plutôt que celle que le SDK sélectionne automatiquement en fonction du type d’appareil et de la taille de l’écran. Le Flow & Paywall Builder n’attribue pas encore d’identifiants de mise en page personnalisés, laissez donc ce paramètre non défini :
AdaptyUI.createFlowView(flow, customLayoutId = "tablet_landscape")
Si aucune mise en page ne correspond à l’ID, le flow se charge sans configuration de vue. Le paramètre est optionnel et prend la valeur null par défaut, donc les appels existants ne sont pas affectés.
Changements de comportement par défaut
Ces changements ne génèrent pas d’erreurs de compilation, testez-les donc à l’exécution :
- Finalisation d’achat : En v3, le comportement par défaut de
paywallViewDidFinishPurchasefermait la vue après tout résultat d’achat autre queAdaptyPurchaseResult.UserCanceled. En v4, le comportement par défaut deflowViewDidFinishPurchasene fait rien, donc un flow reste ouvert après un achat jusqu’à ce que vous le fermiez vous-même — comme sur iOS. Si vous vous appuyiez sur cette fermeture automatique, appelezview.dismiss()une fois l’achat terminé. - Bouton retour Android : En v3, le comportement par défaut de
paywallViewDidPerformActionfermait la vue pourCloseActionetAndroidSystemBackAction. En v4, le comportement par défaut ne gère queCloseAction— le bouton retour système ne ferme plus un flow automatiquement, comme sur iOS où un flow ne peut pas être fermé par un geste système. Donnez aux utilisateurs un moyen explicite de sortir (un bouton Close ou une actionon_device_back), ou fermez la vue vous-même dansflowViewDidPerformAction. - Erreurs de vue : En v3, le comportement par défaut de
paywallViewDidFailRenderingne faisait rien. En v4, le comportement par défaut deflowViewDidReceiveErrorferme la vue — surchargez-le si vous souhaitez garder la vue ouverte ou gérer l’erreur différemment. - Les vues sont à usage unique : Après
dismiss(), la vue est détruite. Appelez à nouveaucreateFlowViewpour afficher le flow une nouvelle fois.
Dépréciation de l’API Onboarding
L’ancienne API onboarding est dépréciée dans la v4 au profit du Flow & Paywall Builder. Elle fonctionne encore, mais sera supprimée dans une future version, prévoyez donc de migrer vos onboardings vers le Flow & Paywall Builder.
Symboles dépréciés : getOnboarding, getOnboardingForDefaultAudience, AdaptyUI.createOnboardingView, AdaptyUI.createNativeOnboardingView et AdaptyUIOnboardingsEventsObserver.