---
title: "Миграция Adapty Android SDK на v3.3"
description: "Перейдите на Adapty Android SDK v3.3 для улучшения производительности и новых функций монетизации."
---

Adapty SDK 3.3.0 — это мажорный релиз, который принёс ряд улучшений, однако для перехода на него могут потребоваться дополнительные шаги миграции.
1. Обновите способ обработки покупок в пейволах, созданных без Paywall Builder. Перестаньте обрабатывать коды ошибок `USER_CANCELED` и `PENDING_PURCHASE`. Отменённая покупка больше не считается ошибкой и теперь будет отображаться в результатах покупки без ошибок.
2. Замените события `onPurchaseCanceled` и `onPurchaseSuccess` новым событием `onPurchaseFinished` для пейволов, созданных с помощью Paywall Builder. Это изменение связано с той же причиной: отменённые покупки больше не считаются ошибками и будут включены в результаты покупки без ошибок.
3. Измените сигнатуру метода `onAwaitingSubscriptionUpdateParams` для пейволов Paywall Builder.
4. Обновите метод, используемый для предоставления резервных пейволов, если вы передаёте URI файла напрямую.
5. Обновите конфигурации интеграций для Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase и Google Analytics, Mixpanel, OneSignal, Pushwoosh.
## Обновление процесса покупки \{#update-making-purchase\}

Ранее отменённые и ожидающие покупки считались ошибками и возвращали коды `USER_CANCELED` и `PENDING_PURCHASE` соответственно.

Теперь для обозначения отменённых, успешных и ожидающих покупок используется новый класс `AdaptyPurchaseResult`. Обновите код покупки следующим образом:
~~~diff
Adapty.makePurchase(activity, product) { result ->
     when (result) {
         is AdaptyResult.Success -> {
-            val info = result.value
-            val profile = info?.profile
-        
-            if (profile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true) {
-                // Grant access to the paid features
-            }
+            when (val purchaseResult = result.value) {
+                is AdaptyPurchaseResult.Success -> {
+                    val profile = purchaseResult.profile
+                    if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) {
+                        // Grant access to the paid features
+                    }
+                }
+
+                is AdaptyPurchaseResult.UserCanceled -> {
+                    // Handle the case where the user canceled the purchase
+                }
+
+                is AdaptyPurchaseResult.Pending -> {
+                    // Handle deferred purchases (e.g., the user will pay offline with cash
+                }
+            }
         }
         is AdaptyResult.Error -> {
             val error = result.error
             // Handle the error
         }
     }
 }
~~~

Полный пример кода смотрите на странице [Совершение покупок в мобильном приложении](android-making-purchases#make-purchase).
## Изменение событий покупки в Paywall Builder \{#modify-paywall-builder-purchase-events\}

1. Добавьте событие `onPurchaseFinished`:
   ```diff showLineNumbers
   + public override fun onPurchaseFinished(
   +     purchaseResult: AdaptyPurchaseResult,
   +     product: AdaptyPaywallProduct,
   +     context: Context,
   + ) {
   +    when (purchaseResult) {
   +        is AdaptyPurchaseResult.Success -> {
   +            // Grant access to the paid features
   +        }
   +        is AdaptyPurchaseResult.UserCanceled -> {
   +            // Handle the case where the user canceled the purchase
   +        }
   +        is AdaptyPurchaseResult.Pending -> {
   +            // Handle deferred purchases (e.g., the user will pay offline with cash)
   +        }
   +    }
   + }
   ```

Для полного примера кода ознакомьтесь с разделом [Успешная, отменённая или ожидающая покупка](android-handling-events#successful-canceled-or-pending-purchase) и описанием события.

2. Удалите обработку события `onPurchaseCancelled`:

   ```diff showLineNumbers
   - public override fun onPurchaseCanceled(
   -     product: AdaptyPaywallProduct,
   -     context: Context,
   - ) {}
   ```

3. Удалите `onPurchaseSuccess`:
   ```diff showLineNumbers
   
   - public override fun onPurchaseSuccess(
   -     profile: AdaptyProfile?,
   -     product: AdaptyPaywallProduct,
   -   context: Context,
   - ) {
   -     // Your logic on successful purchase
   - }
   ```

## Изменение сигнатуры метода onAwaitingSubscriptionUpdateParams \{#change-the-signature-of-onawaitingsubscriptionupdateparams-method\}

Теперь, если новая подписка приобретается, пока другая ещё активна, вызывайте `onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters...))`, если новая подписка должна заменить текущую активную, или `onSubscriptionUpdateParamsReceived(null)`, если активная подписка должна оставаться активной, а новая — добавиться отдельно:
 ```diff showLineNumbers
- public override fun onAwaitingSubscriptionUpdateParams(
-     product: AdaptyPaywallProduct,
-     context: Context,
- ): AdaptySubscriptionUpdateParameters? {
-     return AdaptySubscriptionUpdateParameters(...)
- }
+ public override fun onAwaitingSubscriptionUpdateParams(
+     product: AdaptyPaywallProduct,
+     context: Context,
+     onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback,
+ ) {
+     onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...))
+ }
 ```

Смотрите раздел документации [Обновление подписки](android-handling-events#upgrade-subscription) с финальным примером кода.
## Обновление передачи резервных пейволов \{#update-providing-fallback-paywalls\}

Если вы передаёте URI файла для предоставления резервных пейволов, обновите этот код следующим образом:

<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>

```diff showLineNumbers
val fileUri: Uri = // Get the URI for the file with fallback paywalls
- Adapty.setFallbackPaywalls(fileUri, callback)
+ Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback)
```

</TabItem>
<TabItem value="java" label="Java" default>
```diff showLineNumbers
Uri fileUri = // Получите URI для файла с резервными пейволами
- Adapty.setFallbackPaywalls(fileUri, callback);
+ Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback);
```

</TabItem>
</Tabs>
## Обновление конфигурации SDK сторонних интеграций \{#update-third-party-integration-sdk-configuration\}

Чтобы интеграции корректно работали с Adapty Android SDK 3.3.0 и выше, обновите конфигурации SDK для следующих интеграций, как описано в разделах ниже.
### Adjust

Обновите код вашего мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с Adjust](adjust#connect-your-app-to-adjust).

<Tabs groupId="current-os" queryString>

<TabItem value="v5" label="Adjust 5.x+" default>
```diff showLineNumbers
- Adjust.getAttribution { attribution ->
-     if (attribution == null) return@getAttribution
-
-     Adjust.getAdid { adid ->
-         if (adid == null) return@getAdid
-
-         Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST, adid) { error ->
-             // Handle the error
-         }
-     }
- }

+ Adjust.getAdid { adid ->
+     if (adid == null) return@getAdid
+
+     Adapty.setIntegrationIdentifier("adjust_device_id", adid) { error ->
+         if (error != null) {
+             // Handle the error
+         }
+     }
+ }
+
+ Adjust.getAttribution { attribution ->
+     if (attribution == null) return@getAttribution
+
+     Adapty.updateAttribution(attribution, "adjust") { error ->
+         if (error != null) {
+             // Handle the error
+         }
+     }
+ }
```

</TabItem>

<TabItem value="v4" label="Adjust 4.x" default>

```diff showLineNumbers
 val config = AdjustConfig(context, adjustAppToken, environment)
 config.setOnAttributionChangedListener { attribution ->
     attribution?.let { attribution ->
-         Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST) { error ->
+         Adapty.updateAttribution(attribution, "adjust") { error ->
             if (error != null) {
                 // Handle the error
             }
         }
     }
 }
 Adjust.onCreate(config)
```

</TabItem>
</Tabs>
### AirBridge

Обновите код вашего мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [Настройка SDK для интеграции с AirBridge](airbridge#connect-your-app-to-airbridge).
```diff showLineNumbers
 Airbridge.getDeviceInfo().getUUID(object: AirbridgeCallback.SimpleCallback<String>() {
     override fun onSuccess(result: String) {
-         val params = AdaptyProfileParameters.Builder()
-             .withAirbridgeDeviceId(result)
-             .build()
-         Adapty.updateProfile(params) { error ->
-             if (error != null) {
-                 // Handle the error
-             }
-         }
+         Adapty.setIntegrationIdentifier("airbridge_device_id", result) { error ->
+             if (error != null) {
+                 // Handle the error
+             }
+         }
     }
     override fun onFailure(throwable: Throwable) {
     }
 })
```

### Amplitude

Обновите код своего мобильного приложения, как показано ниже. Полный пример кода см. в разделе [настройка SDK для интеграции с Amplitude](amplitude#sdk-configuration).
```diff showLineNumbers
 // For Amplitude maintenance SDK (obsolete)
 val amplitude = Amplitude.getInstance()
 val amplitudeDeviceId = amplitude.getDeviceId()
 val amplitudeUserId = amplitude.getUserId()

 //for actual Amplitude Kotlin SDK
 val amplitude = Amplitude(
     Configuration(
         apiKey = AMPLITUDE_API_KEY,
         context = applicationContext
     )
 )
 val amplitudeDeviceId = amplitude.store.deviceId
 val amplitudeUserId = amplitude.store.userId

 //

- val params = AdaptyProfileParameters.Builder()
-     .withAmplitudeDeviceId(amplitudeDeviceId)
-     .withAmplitudeUserId(amplitudeUserId)
-     .build()
- Adapty.updateProfile(params) { error ->
-     if (error != null) {
-         // Handle the error
-     }
- }

+ Adapty.setIntegrationIdentifier("amplitude_user_id", amplitudeUserId) { error ->
+     if (error != null) {
+         // Handle the error
+     }
+ }

+ Adapty.setIntegrationIdentifier("amplitude_device_id", amplitudeDeviceId) { error ->
+     if (error != null) {
+         // Handle the error
+     }
+ }
```

### AppMetrica

Обновите код мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [Настройка SDK для интеграции с AppMetrica](appmetrica#sdk-configuration).
```diff showLineNumbers
 val startupParamsCallback = object: StartupParamsCallback {
     override fun onReceive(result: StartupParamsCallback.Result?) {
         val deviceId = result?.deviceId ?: return

-        val params = AdaptyProfileParameters.Builder()
-            .withAppmetricaDeviceId(deviceId)
-            .withAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID")
-            .build()
-        Adapty.updateProfile(params) { error ->
-            if (error != null) {
-                // Handle the error
-            }
-        }

+        Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId) { error ->
+            if (error != null) {
+                // Handle the error
+            }
+        }
+        
+        Adapty.setIntegrationIdentifier("appmetrica_profile_id", "YOUR_ADAPTY_CUSTOMER_USER_ID") { error ->
+            if (error != null) {
+                // Handle the error
+            }
+        }
     }

     override fun onRequestError(
         reason: StartupParamsCallback.Reason,
         result: StartupParamsCallback.Result?
     ) {
         // Handle the error
     }
 }

 AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID))
```

### AppsFlyer

Обновите код своего мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [настройка SDK для интеграции с AppsFlyer](appsflyer#connect-your-app-to-appsflyer).
```diff showLineNumbers
 val conversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener {
     override fun onConversionDataSuccess(conversionData: Map<String, Any>) {
-        Adapty.updateAttribution(
-            conversionData,
-            AdaptyAttributionSource.APPSFLYER,
-            AppsFlyerLib.getInstance().getAppsFlyerUID(context)
-        ) { error ->
-            if (error != null) {
-                // Handle the error
-            }
-        }

+        val uid = AppsFlyerLib.getInstance().getAppsFlyerUID(context)
+        Adapty.setIntegrationIdentifier("appsflyer_id", uid) { error ->
+            if (error != null) {
+                // Handle the error
+            }
+        }
+        Adapty.updateAttribution(conversionData, "appsflyer") { error ->
+            if (error != null) {
+                // Handle the error
+            }
+        }
     }
 }
```

### Branch

Обновите код своего мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с Branch](branch#connect-your-app-to-branch).
```diff showLineNumbers
// Login and update attribution
 Branch.getAutoInstance(this)
   .setIdentity("YOUR_USER_ID") { referringParams, error ->
       referringParams?.let { data ->
-            Adapty.updateAttribution(data, AdaptyAttributionSource.BRANCH) { error ->
-                if (error != null) {
-                    // Handle the error
-                }
-            }
+            Adapty.updateAttribution(data, "branch") { error ->
+                if (error != null) {
+                    // Handle the error
+                }
+            }
       }
   }

 // Logout
 Branch.getAutoInstance(context).logout()
```

### Facebook Ads

Обновите код мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [настройка SDK для интеграции с Facebook Ads](facebook-ads#connect-your-app-to-facebook-ads).
```diff showLineNumbers
- val builder = AdaptyProfileParameters.Builder()
-     .withFacebookAnonymousId(AppEventsLogger.getAnonymousAppDeviceGUID(context))
-   
- Adapty.updateProfile(builder.build()) { error ->
-     if (error != null) {
-        // Handle the error
-     }
- }

+ Adapty.setIntegrationIdentifier(
+     "facebook_anonymous_id",
+     AppEventsLogger.getAnonymousAppDeviceGUID(context)
+ ) { error ->
+     if (error != null) {
+        // Handle the error
+     }
+ }
```

### Firebase и Google Analytics \{#firebase-and-google-analytics\}

Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с Firebase и Google Analytics](firebase-and-google-analytics).

<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
```diff showLineNumbers
 // After Adapty.activate()

 FirebaseAnalytics.getInstance(context).appInstanceId.addOnSuccessListener { appInstanceId ->
-    Adapty.updateProfile(
-        AdaptyProfileParameters.Builder()
-            .withFirebaseAppInstanceId(appInstanceId)
-            .build()
-    ) { error ->
-        if (error != null) {
-            // Handle the error
-        }
-    }
+    Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId) { error ->
+        if (error != null) {
+            // Handle the error
+        }
+    }
 }
```

</TabItem>
<TabItem value="java" label="Java" default>
```diff showLineNumbers
// After Adapty.activate()

- FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> {
-     AdaptyProfileParameters params = new AdaptyProfileParameters.Builder()
-         .withFirebaseAppInstanceId(appInstanceId)
-         .build();
-     
-     Adapty.updateProfile(params, error -> {
-         if (error != null) {
-             // Handle the error
-         }
-     });
- });

+ FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> {
+     Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId, error -> {
+        if (error != null) {
+            // Handle the error
+         }
+     });
+ });
```

</TabItem>
</Tabs>
### Mixpanel

Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в [настройке SDK для интеграции с Mixpanel](mixpanel#sdk-configuration).

```diff showLineNumbers
- val params = AdaptyProfileParameters.Builder()
-     .withMixpanelUserId(mixpanelAPI.distinctId)
-     .build()
-
- Adapty.updateProfile(params) { error ->
-     if (error != null) {
-         // Handle the error
-     }
- }

+ Adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelAPI.distinctId) { error ->
+     if (error != null) {
+         // Handle the error
+     }
+ }
```
### OneSignal

Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с OneSignal](onesignal#sdk-configuration).

<Tabs groupId="current-os" queryString> 

<TabItem value="v5+" label="OneSignal SDK v5+ (текущий)" default> 

<Tabs groupId="current-os" queryString> 

<TabItem value="kotlin" label="Android (Kotlin)" default>
```diff showLineNumbers
 // SubscriptionID 
 val oneSignalSubscriptionObserver = object: IPushSubscriptionObserver {
     override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) {
-        val params = AdaptyProfileParameters.Builder()
-            .withOneSignalSubscriptionId(state.current.id)
-            .build()
-        
-        Adapty.updateProfile(params) { error ->
+        Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.current.id) { error ->
             if (error != null) {
                 // Handle the error
             }
        }
     }
 }
```

</TabItem>
<TabItem value="java" label="(Android) Java" default>

```diff showLineNumbers
 // SubscriptionID 
 IPushSubscriptionObserver oneSignalSubscriptionObserver = state -> {
-    AdaptyProfileParameters params = new AdaptyProfileParameters.Builder()
-            .withOneSignalSubscriptionId(state.getCurrent().getId())
-            .build();
-    Adapty.updateProfile(params, error -> {
+    Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.getCurrent().getId(), error -> {
         if (error != null) {
             // Handle the error
         }
     });
 };
```
</TabItem>
</Tabs>

</TabItem>

<TabItem value="pre-v5" label="OneSignal SDK v. up to 4.x (legacy)" default>

<Tabs groupId="current-os" queryString>

<TabItem value="kotlin" label="Android (Kotlin)" default>
```diff showLineNumbers
 // PlayerID 
 val osSubscriptionObserver = OSSubscriptionObserver { stateChanges ->
     stateChanges?.to?.userId?.let { playerId ->
-        val params = AdaptyProfileParameters.Builder()
-            .withOneSignalPlayerId(playerId)
-            .build()
-      
-        Adapty.updateProfile(params) { error ->
+        Adapty.setIntegrationIdentifier("one_signal_player_id", playerId) { error ->
             if (error != null) {
                 // Handle the error
             }
-        }
     }
 }
```

</TabItem>
<TabItem value="java" label="Java" default>
```diff showLineNumbers
 // PlayerID 
 OSSubscriptionObserver osSubscriptionObserver = stateChanges -> {
     OSSubscriptionState to = stateChanges != null ? stateChanges.getTo() : null;
     String playerId = to != null ? to.getUserId() : null;
     
     if (playerId != null) {
-        AdaptyProfileParameters params1 = new AdaptyProfileParameters.Builder()
-                .withOneSignalPlayerId(playerId)
-                .build();
-        
-        Adapty.updateProfile(params1, error -> {
+        Adapty.setIntegrationIdentifier("one_signal_player_id", playerId, error -> {
             if (error != null) {
                 // Handle the error
             }
-        });
     }
 };
```

</TabItem>

</Tabs>

</TabItem>

</Tabs>
### Pushwoosh

Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с Pushwoosh](pushwoosh#sdk-configuration).

<Tabs groupId="current-os" queryString>
<TabItem value="kotlin" label="Kotlin" default>
```diff showLineNumbers
- val params = AdaptyProfileParameters.Builder()
-     .withPushwooshHwid(Pushwoosh.getInstance().hwid)
-     .build()
  
- Adapty.updateProfile(params) { error ->
+ Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().hwid) { error ->
     if (error != null) {
         // Handle the error
     }
  }
```

</TabItem> <TabItem value="java" label="Java" default>
```diff showLineNumbers
- AdaptyProfileParameters params = new AdaptyProfileParameters.Builder()
-     .withPushwooshHwid(Pushwoosh.getInstance().getHwid())
-     .build();
-
- Adapty.updateProfile(params, error -> {
+ Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().getHwid(), error -> {
     if (error != null) {
         // Handle the error
     }
  });
```

</TabItem> 

</Tabs>