Migrar Adapty Flutter SDK a v. 4.0
Adapty Flutter SDK 4.0 introduce flows y renombra las APIs de paywall en consecuencia. Las nuevas APIs funcionan tanto con el nuevo Flow Builder como con el Paywall Builder existente — no se requieren cambios de configuración en el Adapty Dashboard.
Referencia rápida
| 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 (tipo) | AdaptyFlow |
AdaptyPaywallFetchPolicy (tipo) | AdaptyFlowFetchPolicy |
AdaptyUI().createPaywallView(paywall: paywall) | AdaptyUI().createFlowView(flow: flow) |
AdaptyUIPaywallView (tipo) | AdaptyUIFlowView |
AdaptyUIPaywallPlatformView (widget) | AdaptyUIFlowPlatformView |
AdaptyUI().presentPaywallView(view) / dismissPaywallView(view) | AdaptyUI().presentFlowView(view) / dismissFlowView(view) |
AdaptyUIPaywallsEventsObserver | AdaptyUIFlowsEventsObserver |
AdaptyUI().setPaywallsEventsObserver(observer) | AdaptyUI().setFlowsEventsObserver(observer) |
callbacks paywallViewDid* | callbacks flowViewDid* |
paywallViewDidFailRendering | flowViewDidReceiveError |
AdaptyPaywallProduct mantiene su nombre — los productos siguen perteneciendo a un flow, y getPaywallProducts ahora recibe un AdaptyFlow. Ya no se pasa un locale al recuperar un flow. Las APIs de compra y perfil (makePurchase, restorePurchases, getProfile, identify, etc.) no han cambiado, y tampoco los métodos de vista present, dismiss y showDialog. Algunos comportamientos por defecto han cambiado — consulta Cambios en el comportamiento por defecto. |
Versiones mínimas
El SDK de Adapty para Flutter 4.0 eleva los requisitos mínimos:
- iOS 15.0 — el objetivo de despliegue mínimo para iOS, aumentado desde iOS 13.0.
- Xcode 26 o superior — el SDK nativo de iOS usa Swift tools 6.2.
- Flutter 3.32.0 (Dart 3.8.0) o superior.
Instalación
Actualizar el paquete
El paquete que instales depende de si tu app usa el Modo Infantil.
Para la mayoría de las apps, actualiza adapty_flutter a la v4.0 en tu pubspec.yaml:
dependencies:
adapty_flutter: 4.0.0
Si tu app usa el Modo Infantil, especifica adapty_flutter_kids en su lugar:
dependencies:
adapty_flutter_kids: 4.0.0
Este paquete autónomo elimina el código de IDFA y seguimiento de anuncios para cumplir con los requisitos del App Store. Actualiza la ruta de importación de Dart a package:adapty_flutter_kids/adapty_flutter.dart. Por lo demás, la migración es exactamente igual que la del paquete normal.
El modo Kids también requiere que desactives la recopilación de direcciones IP en el Adapty Dashboard — consulta Kids Mode para ver la configuración completa.
iOS: los SDKs nativos ahora se distribuyen a través de Swift Package Manager
El repositorio de specs de CocoaPods pasará a ser de solo lectura en diciembre de 2026, por lo que a partir de la v4 el SDK nativo de iOS ya no se distribuye a través de CocoaPods — el plugin lo obtiene únicamente a través de Swift Package Manager.
Si usas Flutter 3.32–3.43, activa el soporte de Swift Package Manager una sola vez:
flutter config --enable-swift-package-manager
Flutter 3.44 y versiones posteriores activan Swift Package Manager por defecto, así que no es necesario hacer nada en ese caso.
Obtener flows
getPaywall → getFlow
El tipo devuelto cambia de AdaptyPaywall a AdaptyFlow, y ya no se pasa un locale — cuando renderizas un flow, la localización se resuelve automáticamente; para paywalls personalizados, todos los idiomas configurados se devuelven en flow.remoteConfigs:
- final paywall = await Adapty().getPaywall(placementId: 'YOUR_PLACEMENT_ID', locale: 'en');
+ final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID');
getPaywallForDefaultAudience se renombra de la misma manera:
- final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID', locale: 'en');
+ final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID');
El tipo de política de obtención cambia su nombre de AdaptyPaywallFetchPolicy a AdaptyFlowFetchPolicy; sus opciones (reloadRevalidatingCacheData, returnCacheDataElseLoad, returnCacheDataIfNotExpiredElseLoad) no cambian.
getPaywallProducts(paywall) → getPaywallProducts(flow)
getPaywallProducts mantiene su nombre pero ahora recibe un AdaptyFlow mediante el parámetro flow:
- final products = await Adapty().getPaywallProducts(paywall: paywall);
+ final products = await Adapty().getPaywallProducts(flow: flow);
Modelo de datos
getFlow devuelve un AdaptyFlow en lugar de un AdaptyPaywall, y la estructura del objeto ha cambiado:
Miembro de AdaptyPaywall v3 | Miembro de AdaptyFlow v4 | Acción |
|---|---|---|
remoteConfig (único, nullable) | remoteConfigs (lista) | Un flow lleva un Remote Config por idioma configurado. El getter remoteConfig sigue existiendo y devuelve la primera entrada; para seleccionar un idioma concreto, busca en remoteConfigs por su locale. |
productIdentifiers | productIdentifiers | Se conserva, pero ahora se recopila en todas las variaciones de paywall del flow. Los identificadores por variación están en flow.paywalls[i].productIdentifiers. |
hasViewConfiguration | hasViewConfiguration | Sin cambios. |
placementId (obsoleto) | eliminado | Usa flow.placement.id. |
revision (obsoleto) | eliminado | Usa flow.placement.revision. |
vendorProductIds (obsoleto) | eliminado | Usa productIdentifiers. |
| (nuevo) | paywalls (lista de AdaptyFlowPaywall) | Cada entrada es una variación de paywall en el flow, con su propio name, variationId y productIdentifiers. |
AdaptyPaywallViewConfiguration ya no está expuesto — la configuración de la vista ahora es opaca. Elimina cualquier referencia a este tipo. |
Métodos de paywall web
openWebPaywall y createWebPaywallUrl mantienen sus nombres, pero el parámetro paywall ahora recibe un AdaptyFlowPaywall (una variante de flow) en lugar de un AdaptyPaywall. También puedes seguir pasando un AdaptyPaywallProduct.
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]);
+ }
Seguimiento de vistas de flows
logShowPaywall → logShowFlow
logShowPaywall ha pasado a llamarse logShowFlow y ahora recibe un AdaptyFlow. El evento sigue registrándose contra la misma variación, por lo que las métricas de embudo y prueba A/B existentes siguen funcionando sin cambios en el dashboard.
- await Adapty().logShowPaywall(paywall: paywall);
+ await Adapty().logShowFlow(flow: flow);
Al igual que en v3, no es necesario llamar a este método cuando se muestran flows o paywalls renderizados por el Flow Builder o el Paywall Builder — Adapty registra esas vistas automáticamente.
Mostrar flows
createPaywallView → createFlowView
Renombra el método y pasa el AdaptyFlow mediante el parámetro flow. El resto de parámetros (loadTimeout, preloadProducts, customTags, customTimers, customAssets, productPurchaseParams) no cambian, ni tampoco los métodos de la vista present, dismiss y showDialog:
- final view = await AdaptyUI().createPaywallView(paywall: paywall);
+ final view = await AdaptyUI().createFlowView(flow: flow);
await view.present();
AdaptyUIPaywallView → AdaptyUIFlowView
El tipo de vista ha sido renombrado. Su propiedad paywallVariationId (obsoleta) ha sido eliminada — usa variationId en su lugar:
- void flowViewDidAppear(AdaptyUIPaywallView view) {
+ void flowViewDidAppear(AdaptyUIFlowView view) {
AdaptyUIPaywallPlatformView → AdaptyUIFlowPlatformView
Si incrustas la vista como un widget en tu árbol de widgets, renómbrala y pasa el parámetro flow. Los callbacks de eventos (onDidAppear, onDidFinishPurchase, etc.) conservan sus nombres:
- AdaptyUIPaywallPlatformView(
- paywall: paywall,
+ AdaptyUIFlowPlatformView(
+ flow: flow,
onDidFinishPurchase: (view, product, purchaseResult) { /* … */ },
)
Una vista de flow creada con createFlowView es de un solo uso: tras llamar a dismiss(), la vista se libera de la memoria y no se puede volver a mostrar — llama a createFlowView de nuevo para presentar el flow otra vez.
Manejo de eventos
La clase de observador se renombra de AdaptyUIPaywallsEventsObserver a AdaptyUIFlowsEventsObserver, su método de registro de setPaywallsEventsObserver a setFlowsEventsObserver, y todos los callbacks paywallViewDid* pasan a llamarse flowViewDid*:
- 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);
Ahora hay tres callbacks obligatorios — tu observer no compilará sin ellos:
flowViewDidFinishPurchase: Era opcional en v3, donde el comportamiento por defecto era cerrar la vista tras una compra. Ahora decides qué ocurre: continuar el flow o llamar aview.dismiss().flowViewDidFinishRestore: Obligatorio, igual que en v3.flowViewDidReceiveError: Reemplaza apaywallViewDidFailRenderingy ahora también recibe otros errores de la vista.
Dos cambios menores:
setFlowsEventsObserver(ysetOnboardingsEventsObserver) ahora aceptannullpara desasociar un observador previamente configurado, por lo que el SDK ya no lo retiene.- El nuevo callback opcional
flowViewDidReceiveAnalyticEventestá reservado para eventos analíticos personalizados de un flow. Los flows aún no emiten estos eventos a tu código, por lo que no necesitas implementarlo.
La v4 también añade funcionalidades opcionales a las que puedes suscribirte:
AdaptyUI().setObserverModeResolver(...)con unAdaptyUIObserverModeResolver— gestiona las compras y restauraciones iniciadas desde flows cuando el SDK funciona en modo Observer. Anteriormente, esto solo estaba disponible en los SDKs nativos de iOS y Android. Consulta Presentar flows en modo Observer.AdaptyUI().setSystemRequestsHandler(...)con unAdaptyUISystemRequestsHandler— reservado para solicitudes del sistema desde un flow (permisos del SO y solicitudes de valoración en el App Store). Los flows aún no activan estas solicitudes, por lo que no es necesario registrar un handler.
APIs eliminadas
Estos símbolos fueron declarados obsoletos en la versión 3.x y se eliminan en la v4:
setFallbackPaywalls → setFallback
- await Adapty().setFallbackPaywalls(assetId);
+ await Adapty().setFallback(assetId);
withIdfaCollectionDisabled → withAppleIdfaCollectionDisabled
configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY')
- ..withIdfaCollectionDisabled(true),
+ ..withAppleIdfaCollectionDisabled(true),
Otros miembros eliminados
AdaptyPurchaseResultSuccess.jwsTransaction: UsaappleJwsTransaction.AdaptyUIFlowView.paywallVariationId: UsavariationId.AdaptyUIObserveryAdaptyUI().setObserver(...): UsaAdaptyUIFlowsEventsObserverysetFlowsEventsObserver(...).
Cambios en el comportamiento predeterminado
Estos cambios no causan errores de compilación, así que pruébalos en tiempo de ejecución:
- Compra exitosa: En v3, el comportamiento predeterminado de
paywallViewDidFinishPurchasecerraba la vista. En v4,flowViewDidFinishPurchasees obligatorio y no tiene comportamiento predeterminado — cierra la vista tú mismo si eso es lo que quieres. - Botón Atrás del sistema Android: Ya no cierra un flow de forma predeterminada. La acción se entrega a
flowViewDidPerformActioncomoAndroidSystemBackAction— gestiónala ahí si quieres que el botón Atrás cierre el flow. - Apertura de URLs: El comportamiento predeterminado de
flowViewDidPerformActionahora gestionaOpenUrlActionabriendo la URL de forma nativa (respetando la configuración de navegador interno o externo del dashboard), además de cerrar la vista conCloseAction. Sobreescribe el callback para gestionar las URLs tú mismo. - Errores de vista:
flowViewDidReceiveErrores obligatorio, y el cierre depende de tu implementación. Si tu integración de v3 dependía del cierre automático de la vista al producirse errores de renderizado, llama aview.dismiss()en este callback. - Ciclo de vida de la vista: Cerrar una vista de flow u onboarding la libera de la memoria. Una vista cerrada no puede volver a mostrarse — crea una nueva en su lugar.
Obsolescencia de la API de onboarding
La API de onboarding heredada está obsoleta en v4.0 en favor del Flow Builder. Sigue funcionando, y tu IDE marca los símbolos obsoletos mediante sus anotaciones @Deprecated — no hay advertencias en tiempo de ejecución. Estos símbolos se eliminarán en una versión futura, así que planifica la migración de tus onboardings al Flow Builder.
Símbolos obsoletos: getOnboarding, getOnboardingForDefaultAudience, createOnboardingView, presentOnboardingView, dismissOnboardingView, setOnboardingsEventsObserver, AdaptyOnboarding, AdaptyUIOnboardingView, AdaptyUIOnboardingPlatformView, AdaptyUIOnboardingsEventsObserver, y los modelos de estado, entrada y analíticas de onboarding.