---
title: "Mostrar paywalls de Paywall Builder en modo Observer en el SDK de Android"
description: "Aprende cómo mostrar paywalls en modo observer usando el Paywall Builder de Adapty."
---

Si has personalizado un paywall con el Paywall Builder, no tienes que preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Este tipo de paywall incluye tanto qué mostrar como cómo mostrarlo.

:::warning
Esta sección es exclusivamente para el [modo Observer](observer-vs-full-mode). Si no trabajas en modo Observer, consulta el tema [Android - Mostrar paywalls creados con Paywall Builder](android-present-paywalls).
:::
<Tabs groupId="current-os" queryString>
<TabItem value="SDK3" label="New Paywall Builder (SDK 3.0+)" default>
<details>
   <summary>Antes de empezar a mostrar paywalls (haz clic para expandir)</summary>
1. Configura la integración inicial de Adapty [con Google Play](initial-android) y [con App Store](initial_ios).
   2. Instala y configura el SDK de Adapty. Asegúrate de establecer el parámetro `observerMode` en `true`. Consulta nuestras instrucciones específicas por framework [para Android](sdk-installation-android).
   3. [Crea productos](create-product) en el Adapty Dashboard.
   4. [Configura los paywalls, asígnales productos](create-paywall) y personalízalos usando el Paywall Builder en el Adapty Dashboard.
   5. [Crea placements y asígnales tus paywalls](create-placement) en el Adapty Dashboard.
   6. [Obtén los paywalls del Paywall Builder y su configuración](android-get-pb-paywalls) en el código de tu aplicación móvil.
</details>

<p> </p>

1. Implementa el `AdaptyUiObserverModeHandler`.

El evento `onPurchaseInitiated` te informará de que el usuario ha iniciado una compra. Puedes activar tu flujo de compra personalizado en respuesta a este callback:
<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
   ```kotlin showLineNumbers
   val observerModeHandler =
    AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase ->
       onStartPurchase()
       yourBillingClient.makePurchase(
           product,
           onSuccess = { purchase ->
               onFinishPurchase()
               //handle success
           },
           onError = {
               onFinishPurchase()
               //handle error
           },
           onCancel = {
               onFinishPurchase()
               //handle cancel
           }
       )
   }
   ```
</TabItem>
<TabItem value="java" label="Java" default>
   ```java showLineNumbers
   AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> {
       onStartPurchase.invoke();
       yourBillingClient.makePurchase(
           product,
           purchase -> {
               onFinishPurchase.invoke();
               //handle success
           },
           error -> {
               onFinishPurchase.invoke();
               //handle error
           },
           () -> { //cancellation
               onFinishPurchase.invoke();
               //handle cancel
           }
       );
   };
   ```
</TabItem>
</Tabs>
Para manejar las restauraciones en el modo Observer, sobreescribe `getRestoreHandler()`. Por defecto devuelve `null`, lo que utiliza el flujo integrado de `Adapty.restorePurchases()` de Adapty. Para proporcionar tu propia implementación de restauración:

<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
   ```kotlin showLineNumbers
   val observerModeHandler = object : AdaptyUiObserverModeHandler {
       // onPurchaseInitiated implementation (see above)

       override fun getRestoreHandler() =
           AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore ->
               onStartRestore()
               yourBillingClient.restorePurchases(
                   onSuccess = { restoredPurchases ->
                       onFinishRestore()
                       //handle successful restore
                   },
                   onError = {
                       onFinishRestore()
                       //handle error
                   }
               )
           }
   }
   ```
</TabItem>
<TabItem value="java" label="Java" default>
   ```java showLineNumbers
   AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() {
       // onPurchaseInitiated implementation (see above)

       @Override
       public RestoreHandler getRestoreHandler() {
           return (onStartRestore, onFinishRestore) -> {
               onStartRestore.invoke();
               yourBillingClient.restorePurchases(
                   restoredPurchases -> {
                       onFinishRestore.invoke();
                       //handle successful restore
                   },
                   error -> {
                       onFinishRestore.invoke();
                       //handle error
                   }
               );
           };
       }
   };
   ```
</TabItem>
</Tabs>
Recuerda invocar los siguientes callbacks para notificar a AdaptyUI sobre el proceso de compra o restauración. Esto es necesario para que el paywall funcione correctamente, por ejemplo, para mostrar el loader:
| Callback           | Descripción                                                                                          |
   | :----------------- |:-----------------------------------------------------------------------------------------------------|
   | onStartPurchase()  | El callback debe invocarse para notificar a AdaptyUI que la compra ha comenzado.                     |
   | onFinishPurchase() | El callback debe invocarse para notificar a AdaptyUI que la compra ha finalizado.                    |
   | onStartRestore()   | Opcional. El callback puede invocarse para notificar a AdaptyUI que la restauración ha comenzado.    |
   | onFinishRestore()  | Opcional. El callback puede invocarse para notificar a AdaptyUI que la restauración ha finalizado.   |
2. Para mostrar el paywall visual en la pantalla del dispositivo, primero debes configurarlo.

<Tabs groupId="current-os" queryString>
<TabItem value="views" label="Views" default>

Para ello, llama al método `AdaptyUI.getPaywallView()` o crea el `AdaptyPaywallView` directamente:

<Tabs groupId="current-os" queryString>
  <TabItem value="kotlin" label="Kotlin (opción 1)" default>
```kotlin showLineNumbers
   val paywallView = AdaptyUI.getPaywallView(
       activity,
       viewConfiguration,
       products,
       eventListener,
       personalizedOfferResolver,
       tagResolver,
       timerResolver,
       observerModeHandler, 
   )
```

</TabItem>
<TabItem value="kotlin2" label="Kotlin (opción 2)" default>
```kotlin showLineNumbers
   val paywallView =
        AdaptyPaywallView(activity) // or retrieve it from xml
   ...
   with(paywallView) {
       showPaywall(
           viewConfiguration,
           products,
					 eventListener,
           personalizedOfferResolver,
           tagResolver,
           timerResolver,
					 observerModeHandler,
       )
   }
```

</TabItem>
<TabItem value="java" label="Java (opción 1)" default>
```java showLineNumbers
AdaptyPaywallView paywallView = AdaptyUI.getPaywallView(
        activity,
        viewConfiguration,
        products,
        eventListener,
        personalizedOfferResolver,
        tagResolver,
        timerResolver,
        observerModeHandler
);
```

</TabItem>
<TabItem value="java2" label="Java (opción 2)" default>
```java showLineNumbers
AdaptyPaywallView paywallView =
  new AdaptyPaywallView(activity); //añadir a la jerarquía de vistas si es necesario, o recibirlo desde xml
...
paywallView.showPaywall(viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler);
```

</TabItem>
<TabItem value="XML" label="XML" default>

```xml showLineNumbers
<com.adapty.ui.AdaptyPaywallView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

</TabItem>
</Tabs>
Después de crear la vista correctamente, puedes añadirla a la jerarquía de vistas y mostrarla.

</TabItem>
<TabItem value="compose" label="Jetpack Compose" default>

Para hacerlo, utiliza esta función composable:

```kotlin showLineNumbers
AdaptyPaywallScreen(
    viewConfiguration,
    products,
    eventListener,
    personalizedOfferResolver,
    tagResolver,
    timerResolver,
)
```

</TabItem>
</Tabs>

   Parámetros de la solicitud:
| Parámetro | Presencia | Descripción |
|---------|--------|-----------|
| **Products** | opcional | Proporciona un array de `AdaptyPaywallProduct` para optimizar el momento de visualización de los productos en pantalla. Si se pasa `null`, AdaptyUI obtendrá automáticamente los productos necesarios. |
| **ViewConfiguration** | obligatorio | Proporciona un objeto `AdaptyViewConfiguration` que contiene los detalles visuales del paywall. Usa el método `Adapty.getViewConfiguration(paywall)` para cargarlo. Consulta el tema [Obtener la configuración visual del paywall](#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) para más detalles. |
| **EventListener** | opcional | Proporciona un `AdaptyUiEventListener` para observar los eventos del paywall. Se recomienda extender `AdaptyUiDefaultEventListener` para mayor comodidad. Consulta el tema [Gestionar eventos del paywall](android-handling-events) para más detalles. |
| **PersonalizedOfferResolver** | opcional | Para indicar precios personalizados ([leer más](https://developer.android.com/google/play/billing/integrate#personalized-price)), implementa `AdaptyUiPersonalizedOfferResolver` y añade tu propia lógica que mapee `AdaptyPaywallProduct` a `true` si el precio del producto es personalizado, o a `false` en caso contrario. |
| **TagResolver** | opcional | Usa `AdaptyUiTagResolver` para resolver etiquetas personalizadas dentro del texto del paywall. Este resolver recibe un parámetro de etiqueta y lo resuelve en la cadena de texto correspondiente. Consulta el tema [Etiquetas personalizadas en Paywall Builder](custom-tags-in-paywall-builder) para más detalles. |
| **ObserverModeHandler** | obligatorio en modo Observer | El `AdaptyUiObserverModeHandler` que implementaste en el paso anterior. |
| **variationId** | obligatorio | El identificador de cadena de la variante. Puedes obtenerlo usando la propiedad `variationId` del objeto [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/). |
| **transaction** | obligatorio | <p>Para iOS, StoreKit 1: un objeto [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction).</p><p>Para iOS, StoreKit 2: objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).</p><p>Para Android: identificador de cadena (`purchase.getOrderId()`) de la compra, donde la compra es una instancia de la clase [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la biblioteca de facturación.</p> |
</TabItem>
<TabItem value="SDK2" label="Legacy Paywall Builder (SDK hasta 2.x)" default>
<details>
   <summary>Antes de empezar a mostrar paywalls (Haz clic para ampliar)</summary>
1. Configura la integración inicial de Adapty [con Google Play](initial-android) y [con App Store](initial_ios).
2. Instala y configura el SDK de Adapty. Asegúrate de establecer el parámetro `observerMode` en `true`. Consulta las instrucciones específicas para cada framework: [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) y [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk).
3. [Crea productos](create-product) en el Adapty Dashboard.
4. [Configura los paywalls, asígnales productos](create-paywall) y personalízalos con el Paywall Builder en el Adapty Dashboard.
5. [Crea placements y asígnales tus paywalls](create-placement) en el Adapty Dashboard.
6. [Obtén los paywalls del Paywall Builder y su configuración](android-get-pb-paywalls) en el código de tu aplicación móvil.
</details>
1. Implementa el `AdaptyUiObserverModeHandler`. El callback de `AdaptyUiObserverModeHandler` (`onPurchaseInitiated`) te avisa cuando el usuario inicia una compra. Puedes activar tu flujo de compra personalizado en respuesta a este callback así:
<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
   ```kotlin showLineNumbers
   val observerModeHandler =
   AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase ->
       onStartPurchase()
       yourBillingClient.makePurchase(
           product,
           onSuccess = { purchase ->
               onFinishPurchase()
               //handle success
           },
           onError = {
               onFinishPurchase()
               //handle error
           },
           onCancel = {
               onFinishPurchase()
               //handle cancel
           }
       )
   }
   ```
</TabItem>
<TabItem value="java" label="Java" default>
   ```java showLineNumbers
   AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> {
       onStartPurchase.invoke();
       yourBillingClient.makePurchase(
           product,
           purchase -> {
               onFinishPurchase.invoke();
               //handle success
           },
           error -> {
               onFinishPurchase.invoke();
               //handle error
           },
           () -> { //cancellation
               onFinishPurchase.invoke();
               //handle cancel
           }
       );
   };
   ```
</TabItem>
</Tabs>
También recuerda invocar estos callbacks en AdaptyUI. Esto es necesario para el correcto funcionamiento del paywall, como mostrar el loader, entre otras cosas:
| Callback en Kotlin | Callback en Java          | Descripción                                                                                                                                      |
   | :----------------- | :------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- |
   | onStartPurchase()  | onStartPurchase.invoke()  | Este callback debe invocarse para notificar a AdaptyUI que la compra ha comenzado.                                                               |
   | onFinishPurchase() | onFinishPurchase.invoke() | Este callback debe invocarse para notificar a AdaptyUI que la compra ha finalizado correctamente, que ha fallado, o que ha sido cancelada. |
2. Para mostrar el paywall visual, primero debes inicializarlo. Para ello, llama al método `AdaptyUI.getPaywallView()` o crea el `AdaptyPaywallView` directamente:

<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
   ```kotlin showLineNumbers
   val paywallView = AdaptyUI.getPaywallView(
       activity,
       viewConfiguration,
       products,
       AdaptyPaywallInsets.of(topInset, bottomInset),
       eventListener,
       personalizedOfferResolver,
       tagResolver,
       observerModeHandler,
   )

   //======= OR =======
val paywallView =
        AdaptyPaywallView(activity) // or retrieve it from xml
   ...
   with(paywallView) {
       setEventListener(eventListener)
       setObserverModeHandler(observerModeHandler)
       showPaywall(
           viewConfiguration,
           products,
           AdaptyPaywallInsets.of(topInset, bottomInset),
           personalizedOfferResolver,
           tagResolver,
       )
   }
   ```
</TabItem>
<TabItem value="java" label="Java" default>
   ```java showLineNumbers
   AdaptyPaywallView paywallView = AdaptyUI.getPaywallView(
           activity,
           viewConfiguration,
           products,
           AdaptyPaywallInsets.of(topInset, bottomInset),
           eventListener,
           personalizedOfferResolver,
           tagResolver,
           observerModeHandler
   );
//======= OR =======
AdaptyPaywallView paywallView =
     new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml
   ...
   paywallView.setEventListener(eventListener);
   paywallView.setObserverModeHandler(observerModeHandler);
   paywallView.showPaywall(viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver);
   ```
</TabItem>
<TabItem value="XML" label="XML" default>
   ```xml showLineNumbers
   <com.adapty.ui.AdaptyPaywallView xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />
   ```
</TabItem>
</Tabs>
Tras crear la vista correctamente, puedes añadirla a la jerarquía de vistas y mostrarla.

Parámetros de la solicitud:
| Parámetro | Presencia | Descripción                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
|---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Products** | opcional | Proporciona un array de `AdaptyPaywallProduct` para optimizar el tiempo de visualización de los productos en pantalla. Si se pasa `null`, AdaptyUI obtendrá automáticamente los productos necesarios.                                                                                                                                                                                                                                                                                                                                       |
| **ViewConfiguration** | requerido | Suministra un objeto `AdaptyViewConfiguration` que contiene los detalles visuales del paywall. Usa el método `Adapty.getViewConfiguration(paywall)` para cargarlo. Consulta el tema [Obtener la configuración visual del paywall](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) para más detalles.                                                                                                                                                                      |
| **Insets** | requerido | Define un objeto `AdaptyPaywallInsets` con información sobre el área solapada por las barras del sistema, creando márgenes verticales para el contenido. Si ni la barra de estado ni la barra de navegación solapan el `AdaptyPaywallView`, pasa `AdaptyPaywallInsets.NONE`. En modo pantalla completa donde las barras del sistema solapan parte de tu interfaz, obtén los insets como se muestra debajo de la tabla.                                                                                                                                |
| **EventListener** | opcional | Proporciona un `AdaptyUiEventListener` para observar los eventos del paywall. Se recomienda extender `AdaptyUiDefaultEventListener` para facilitar su uso. Consulta el tema [Gestión de eventos del paywall](android-handling-events) para más detalles.                                                                                                                                                                                                                                                                                |
| **PersonalizedOfferResolver** | opcional | Para indicar precios personalizados ([leer más](https://developer.android.com/google/play/billing/integrate#personalized-price)), implementa `AdaptyUiPersonalizedOfferResolver` y pasa tu propia lógica que mapea `AdaptyPaywallProduct` a `true` si el precio del producto es personalizado, o `false` en caso contrario.                                                                                                                                                                                               |
| **TagResolver** | opcional | Usa `AdaptyUiTagResolver` para resolver etiquetas personalizadas dentro del texto del paywall. Este resolver toma un parámetro de etiqueta y lo resuelve en la cadena correspondiente. Consulta el tema [Etiquetas personalizadas en Paywall Builder](custom-tags-in-paywall-builder) para más detalles.                                                                                                                                                                                                                              |
| **ObserverModeHandler** | requerido en modo Observer | El `AdaptyUiObserverModeHandler` que implementaste en el paso anterior.                                                                                                                                                                                                                                                                                                                                                                                                                              |
| **variationId** | requerido | El identificador de cadena de la variante. Puedes obtenerlo usando la propiedad `variationId` del objeto [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/).                                                                                                                                                                                                                                                                                                                                                        |
| **transaction** | requerido | <p>Para iOS, StoreKit 1: un objeto [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction).</p><p>Para iOS, StoreKit 2: un objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).</p><p>Para Android: el identificador de cadena (`purchase.getOrderId()`) de la compra, donde la compra es una instancia de la clase [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la biblioteca de facturación.</p> |
Para el modo de pantalla completa, donde las barras del sistema se superponen a parte de tu UI, obtén los insets de la siguiente manera:

<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
   ```kotlin showLineNumbers
   import androidx.core.graphics.Insets
   import androidx.core.view.ViewCompat
   import androidx.core.view.WindowInsetsCompat

   //create extension function
   fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) {
       ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
           val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
           ViewCompat.setOnApplyWindowInsetsListener(this, null)
           action(systemBarInsets)
           insets
       }
   }
   //and then use it with the view
   paywallView.onReceiveSystemBarsInsets { insets ->
       val paywallInsets = AdaptyPaywallInsets.of(insets.top, insets.bottom)
       paywallView.setEventListener(eventListener)
       paywallView.setObserverModeHandler(observerModeHandler)
       paywallView.showPaywall(viewConfig, products, paywallInsets, personalizedOfferResolver, tagResolver)
   }
   ```
</TabItem>
<TabItem value="java" label="Java" default>
   ```java showLineNumbers
   import androidx.core.graphics.Insets;
   import androidx.core.view.ViewCompat;
   import androidx.core.view.WindowInsetsCompat;

   ...

   ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> {
       Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
       ViewCompat.setOnApplyWindowInsetsListener(paywallView, null);
     
       AdaptyPaywallInsets paywallInsets =
                    AdaptyPaywallInsets.of(systemBarInsets.top, systemBarInsets.bottom);
       paywallView.setEventListener(eventListener);
       paywallView.setObserverModeHandler(observerModeHandler);
       paywallView.showPaywall(viewConfiguration, products, paywallInsets, personalizedOfferResolver, tagResolver);
               
       return insets;
   });
   ```
</TabItem>
</Tabs>

   Devuelve:
| Objeto              | Descripción                                        |
   | :------------------ | :------------------------------------------------- |
   | `AdaptyPaywallView` | objeto que representa la pantalla del paywall solicitado. |

:::warning
No olvides [Asociar paywalls a transacciones de compra](report-transactions-observer-mode-android). De lo contrario, Adapty no podrá determinar el paywall de origen de la compra.
:::

</TabItem> 
</Tabs>