---
title: "Миграция Adapty Android SDK на версию 4.0"
description: "Миграция на Adapty Android SDK v4.0 (beta): замена paywall API на flow API, совместимых как с Flow Builder, так и с Paywall Builder."
---

Adapty Android SDK 4.0 (beta) вводит флоу и переименовывает соответствующие paywall API. Новые API работают как с новым Flow Builder, так и с существующим Paywall Builder — никаких изменений в настройках дашборда Adapty не требуется.
## Краткая справка \{#quick-reference\}
| v3 | v4 |
|---|---|
| `Adapty.getPaywall(placementId, locale)` | `Adapty.getFlow(placementId)` |
| `Adapty.getPaywallForDefaultAudience(placementId, locale)` | `Adapty.getFlowForDefaultAudience(placementId)` |
| `AdaptyUI.getViewConfiguration(paywall)` | `AdaptyUI.getFlowConfiguration(flow, locale)` |
| `AdaptyUI.LocalizedViewConfiguration` | `AdaptyUI.FlowConfiguration` |
| `Adapty.getPaywallProducts(paywall)` | `Adapty.getPaywallProducts(flow)` |
| `Adapty.logShowPaywall(paywall)` | `Adapty.logShowFlow(flow)` |
| `AdaptyPaywall` | `AdaptyFlow` |
| `AdaptyUI.getPaywallView(...)` | `AdaptyUI.getFlowView(...)` |
| `AdaptyPaywallView` | `AdaptyFlowView` |
| `AdaptyPaywallScreen` (Compose) | `AdaptyFlowScreen` |
| `showPaywall(...)` | `showFlow(...)` |
| `AdaptyPaywallInsets` | `AdaptyFlowInsets` |
| `AdaptyUiEventListener` | `AdaptyFlowEventListener` |
| `AdaptyUiDefaultEventListener` | `AdaptyFlowDefaultEventListener` |
| `onPaywallShown` / `onPaywallClosed` | `onFlowShown` / `onFlowClosed` |
| `onRenderingError` | `onError` |
| `Adapty.updateAttribution(attribution, source)` (`source: String`) | `Adapty.updateAttribution(attribution, source)` (`source: AdaptyAttributionSource`) |
| `Adapty.setIntegrationIdentifier(key, value)` | `Adapty.setIntegrationIdentifier(AdaptyIntegrationIdentifier)` |
`AdaptyPaywallProduct` сохраняет своё название — продукты по-прежнему принадлежат флоу, а `getPaywallProducts` теперь принимает `AdaptyFlow`. Остальные методы `AdaptyFlowEventListener` (`onProductSelected`, `onPurchaseStarted`, `onPurchaseFinished`, `onPurchaseFailure`, `onRestoreSuccess`, `onRestoreFailure`, `onActionPerformed`, `onAwaitingPurchaseParams`, `onLoadingProductsFailure` и т. д.) сохраняют свои названия и сигнатуры.
## Установка \{#installation\}

Adapty Android SDK 4.0 — это предрелизная версия, поэтому вместо динамического диапазона необходимо указать точную версию: задайте версию `adapty-bom` как `4.0.0-beta.1` и синхронизируйте проект. BOM автоматически подберёт подходящие версии `android-sdk` и `android-ui`. Инструкции по подключению зависимостей см. в разделе [Установка Adapty SDK](sdk-installation-android).
## Удалённые и устаревшие API \{#removed-and-deprecated-apis\}

- **`Adapty.makePurchase(activity, product, subscriptionUpdateParams, isOfferPersonalized, callback)`** — удалён. Этот перегруженный метод был помечен как устаревший в v3. Передавайте те же параметры через `AdaptyPurchaseParameters`:
```diff showLineNumbers
- Adapty.makePurchase(activity, product, subscriptionUpdateParams, isOfferPersonalized) { result -> /* ... */ }
+ val params = AdaptyPurchaseParameters.Builder()
+     .withSubscriptionUpdateParams(subscriptionUpdateParams)
+     .withOfferPersonalized(isOfferPersonalized)
+     .build()
+ Adapty.makePurchase(activity, product, params) { result -> /* ... */ }
```

- **Онбординги устарели.** `AdaptyUI.getOnboardingView` и `AdaptyUI.getOnboardingConfiguration` помечены как `@Deprecated` в версии 4.0 — переносите онбординги во флоу, созданные в [Flow Builder](adapty-flow-builder).
## Получение флоу \{#fetching-flows\}
### getPaywall + getViewConfiguration → getFlow + getFlowConfiguration

Тип возвращаемого значения при получении данных изменяется с `AdaptyPaywall` на `AdaptyFlow`, а загрузчик конфигурации переименован с `AdaptyUI.getViewConfiguration` на `AdaptyUI.getFlowConfiguration` (возвращает `AdaptyUI.FlowConfiguration` вместо `AdaptyUI.LocalizedViewConfiguration`). Параметр `locale` перемещён из вызова получения данных в `getFlowConfiguration`:
```diff showLineNumbers
- Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result ->
+ Adapty.getFlow("YOUR_PLACEMENT_ID") { result ->
      if (result is AdaptyResult.Success) {
-         val paywall = result.value
-         if (!paywall.hasViewConfiguration) return@getPaywall
-         AdaptyUI.getViewConfiguration(paywall) { configResult ->
+         val flow = result.value
+         if (!flow.hasViewConfiguration) return@getFlow
+         AdaptyUI.getFlowConfiguration(flow, locale = "en") { configResult ->
              if (configResult is AdaptyResult.Success) {
                  val flowConfiguration = configResult.value
              }
          }
      }
  }
```

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

`getPaywallProducts` теперь принимает `AdaptyFlow`, возвращаемый методом `Adapty.getFlow`:

```diff showLineNumbers
- Adapty.getPaywallProducts(paywall) { result -> /* products */ }
+ Adapty.getPaywallProducts(flow) { result -> /* products */ }
```
## Отслеживание просмотров флоу \{#tracking-flow-views\}
### logShowPaywall → logShowFlow

`logShowPaywall` переименован в `logShowFlow` и теперь принимает `AdaptyFlow` вместо `AdaptyPaywall`. Событие по-прежнему фиксируется для той же вариации, поэтому существующие метрики воронок и A/B-тестов продолжат работать без изменений в дашборде.

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

Как и в v3, вам не нужно вызывать этот метод при отображении флоу или пейволов, отрендеренных с помощью [Flow Builder](adapty-flow-builder) или [Paywall Builder](adapty-paywall-builder) — Adapty отслеживает эти просмотры автоматически.
## Отображение флоу \{#displaying-flows\}
### getPaywallView / AdaptyPaywallView → getFlowView / AdaptyFlowView

Переименуйте фабричный метод и тип представления, а также передайте `AdaptyUI.FlowConfiguration`:

```diff showLineNumbers
- val paywallView = AdaptyUI.getPaywallView(
-     activity,
-     viewConfiguration,
-     products,
-     eventListener,
- )
+ val flowView = AdaptyUI.getFlowView(
+     activity,
+     flowConfiguration,
+     products,
+     eventListener,
+ )
```

Если вы создаёте представление напрямую, метод показа также переименован:
```diff showLineNumbers
- val paywallView = AdaptyPaywallView(activity)
- paywallView.showPaywall(viewConfiguration, products, eventListener)
+ val flowView = AdaptyFlowView(activity)
+ flowView.showFlow(flowConfiguration, products, eventListener)
```

В XML-разметке обновите тег представления:

```diff showLineNumbers
- <com.adapty.ui.AdaptyPaywallView ... />
+ <com.adapty.ui.AdaptyFlowView ... />
```
Необязательный параметр `personalizedOfferResolver` удалён из `getFlowView` / `showFlow` / `AdaptyFlowScreen`. Чтобы указать персонализированную цену, задайте её для каждого продукта через `onAwaitingPurchaseParams` (`AdaptyPurchaseParameters.Builder().withOfferPersonalized(true)`). Новый необязательный параметр `customAssets` позволяет переопределять изображения и видео во время выполнения — подробнее см. в разделе [Кастомизация ресурсов](android-get-pb-paywalls#customize-assets).
### AdaptyPaywallScreen → AdaptyFlowScreen

В Jetpack Compose переименуйте компонуемый элемент и обновите параметр конфигурации:

```diff showLineNumbers
- AdaptyPaywallScreen(
-     viewConfiguration,
+ AdaptyFlowScreen(
+     flowConfiguration,
      products,
      eventListener,
  )
```
## Обработка событий \{#handling-events\}

Слушатель событий переименован с `AdaptyUiEventListener` на `AdaptyFlowEventListener` (а `AdaptyUiDefaultEventListener` — на `AdaptyFlowDefaultEventListener`). Большинство названий методов не изменились; переименованы только колбэки жизненного цикла и рендеринга:
```diff showLineNumbers
- class YourListener : AdaptyUiDefaultEventListener() {
+ class YourListener : AdaptyFlowDefaultEventListener() {

-     override fun onPaywallShown(context: Context) {}
-     override fun onPaywallClosed() {}
+     override fun onFlowShown(context: Context) {}
+     override fun onFlowClosed() {}

-     override fun onRenderingError(error: AdaptyError, context: Context) {}
+     override fun onError(error: AdaptyError, context: Context) {}
  }
```

Тела существующих обработчиков менять не нужно — достаточно переименовать тип и переопределения. `onError` срабатывает для тех же ошибок рендеринга, что и `onRenderingError`, плюс для других ошибок времени выполнения, не связанных с покупками. Полный список коллбэков см. в разделе [Обработка событий флоу и пейвола](android-handling-events).
## Идентификаторы атрибуции и интеграций \{#attribution-and-integration-identifiers\}
### updateAttribution

Параметр `source` меняется с `String` на новый тип `AdaptyAttributionSource`, а `attribution` теперь является `Map<String, Any>` (также доступна перегрузка с `String` в формате JSON). Используйте один из предопределённых источников:

```diff showLineNumbers
- Adapty.updateAttribution(attribution, "appsflyer") { error -> /* handle the error */ }
+ Adapty.updateAttribution(attribution, AdaptyAttributionSource.APPSFLYER) { error -> /* handle the error */ }
```
Предопределённые источники: `AdaptyAttributionSource.APPLE_ADS`, `.ADJUST`, `.APPSFLYER`, `.BRANCH`, `.TENJIN`. Для любого другого источника создайте его из строки: `AdaptyAttributionSource("your_source")`.
### setIntegrationIdentifier

`setIntegrationIdentifier(key, value)` заменён методом, принимающим одно или несколько значений `AdaptyIntegrationIdentifier`. Используйте предопределённые константы `Key` вместо строковых ключей:

```diff showLineNumbers
- Adapty.setIntegrationIdentifier("appsflyer_id", appsFlyerId) { error -> /* handle the error */ }
+ Adapty.setIntegrationIdentifier(
+     AdaptyIntegrationIdentifier(AdaptyIntegrationIdentifier.Key.APPSFLYER_ID, appsFlyerId)
+ ) { error -> /* handle the error */ }
```

Несколько идентификаторов можно задать за один вызов:
```kotlin showLineNumbers
Adapty.setIntegrationIdentifier(
    listOf(
        AdaptyIntegrationIdentifier(AdaptyIntegrationIdentifier.Key.APPSFLYER_ID, appsFlyerId),
        AdaptyIntegrationIdentifier(AdaptyIntegrationIdentifier.Key.ADJUST_DEVICE_ID, adjustDeviceId),
    )
) { error -> /* handle the error */ }
```

Замените каждую старую строку ключа соответствующей константой `Key`:
| v3 key | v4 `AdaptyIntegrationIdentifier.Key` |
|---|---|
| `"adjust_device_id"` | `ADJUST_DEVICE_ID` |
| `"airbridge_device_id"` | `AIRBRIDGE_DEVICE_ID` |
| `"amplitude_user_id"` | `AMPLITUDE_USER_ID` |
| `"amplitude_device_id"` | `AMPLITUDE_DEVICE_ID` |
| `"appmetrica_device_id"` | `APPMETRICA_DEVICE_ID` |
| `"appmetrica_profile_id"` | `APPMETRICA_PROFILE_ID` |
| `"appsflyer_id"` | `APPSFLYER_ID` |
| `"branch_id"` | `BRANCH_ID` |
| `"facebook_anonymous_id"` | `FACEBOOK_ANONYMOUS_ID` |
| `"firebase_app_instance_id"` | `FIREBASE_APP_INSTANCE_ID` |
| `"mixpanel_user_id"` | `MIXPANEL_USER_ID` |
| `"one_signal_subscription_id"` | `ONE_SIGNAL_SUBSCRIPTION_ID` |
| `"one_signal_player_id"` | `ONE_SIGNAL_PLAYER_ID` |
| `"posthog_distinct_user_id"` | `POSTHOG_DISTINCT_USER_ID` |
| `"pushwoosh_hwid"` | `PUSHWOOSH_HWID` |
| `"tenjin_analytics_installation_id"` | `TENJIN_ANALYTICS_INSTALLATION_ID` |