迁移 Adapty Flutter SDK 至 v3.3

Adapty SDK 3.3.0 是一个重大版本更新,带来了一些改进,但可能需要你执行一些迁移步骤。


title: “迁移指南:从 Adapty iOS SDK v2.x 迁移至 v3.x” description: “将您的 iOS 应用从 Adapty SDK v2.x 无缝迁移至 v3.x,遵循我们的分步指南,了解关键变更,轻松完成集成升级。” metadataTitle: “iOS SDK v2.x 至 v3.x 迁移指南 | Adapty 文档”

Adapty SDK v3.x 是一个重大版本更新,包含多项破坏性变更。本指南重点介绍这些变更,帮助您顺利完成迁移。

公共 API 变更

AdaptyUI 更名

AdaptyUI 已重命名为 AdaptyUI——抱歉,只是开个玩笑😄 实际上没有变化,但我们确实针对新版付费墙编辑工具对 AdaptyUI 进行了大量更新。

获取付费墙和产品

在 Adapty SDK v3.x 中,getPaywall 方法的加载策略机制已更新。

在 v3.x 中,我们移除了 PaywallFetchPolicy,转而采用更简洁的方案:默认加载已缓存的数据(若无缓存则从远端拉取),同时开放了直接从远端强制拉取的选项。

备用付费墙

在 v3.x 中,设置备用付费墙的方法已更新。

移除 getProductsIntroductoryOfferEligibility

getProductsIntroductoryOfferEligibility 方法已从 SDK 中移除。新用户优惠资格信息现在直接包含在 AdaptyPaywallProduct 对象中。

AdaptyPaywallProduct 变更

AdaptyPaywallProduct 的结构已更新。在 v3.x 中,subscriptionOffer 属性会自动包含相应的优惠(新用户优惠或促销活动),无需额外的资格检查。

v2.x 属性v3.x 属性
introductoryDiscount现已合并至 subscriptionOffer
promotionalDiscount现已合并至 subscriptionOffer
promotionalOfferId现已合并至 subscriptionOffer

subscriptionOffer 属性返回适合当前用户的最优优惠:若用户符合新用户优惠资格,则返回新用户优惠;若存在促销活动,则返回促销活动;其他情况返回 nil

第三方集成配置变更

在 v3.x 中,多个第三方集成的配置方式已更新,从专有方法迁移至通用的 setIntegrationIdentifier 方法。

Adjust

AirBridge

Amplitude

AppMetrica

AppsFlyer

Branch

Facebook Ads

Firebase 与 Google Analytics

Mixpanel

OneSignal

Pushwoosh

观察者模式

在 v3.x 中,观察者模式的实现方式已更新。

更新备用付费墙的提供方式

此前,该方法需要以 JSON 字符串(jsonString)的形式传入备用付费墙,现在改为传入本地备用文件的路径(assetId)。

 import 'dart:async' show Future;
 import 'dart:io' show Platform;
-import 'package:flutter/services.dart' show rootBundle;

-final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json';
-final jsonString = await rootBundle.loadString(filePath);
+final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json';

 try {
-  await adapty.setFallbackPaywalls(jsonString);
+  await adapty.setFallbackPaywalls(assetId);
 } on AdaptyError catch (adaptyError) {
   // handle the error
 } catch (e) {
 }

完整的代码示例请参阅使用备用付费墙页面。

移除 getProductsIntroductoryOfferEligibility 方法

在 Adapty iOS SDK 3.3.0 之前,无论用户是否具有资格,产品对象始终包含优惠信息。您需要在使用优惠之前手动检查资格。

现在,只有当用户具有资格时,产品对象才会包含优惠信息。这意味着您不再需要检查资格——如果存在优惠,则用户具有资格。

更新第三方集成 SDK 配置

为确保集成在 Adapty Flutter SDK 3.3.0 及更高版本中正常工作,请按照以下各节所述更新您的 SDK 配置。

Adjust

按照以下方式更新您的移动应用代码。完整代码示例请参阅 Adjust 集成的 SDK 配置

 import 'package:adjust_sdk/adjust.dart';
 import 'package:adjust_sdk/adjust_config.dart';

 try {
   final adid = await Adjust.getAdid();

   if (adid == null) {
     // handle the error
   }

+   await Adapty().setIntegrationIdentifier(
+     key: "adjust_device_id", 
+     value: adid,
+   );

   final attributionData = await Adjust.getAttribution();

   var attribution = Map<String, String>();

   if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!;
   if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!;
   if (attributionData.network != null) attribution['network'] = attributionData.network!;
   if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!;
   if (attributionData.creative != null) attribution['creative'] = attributionData.creative!;
   if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!;
   if (attributionData.costType != null) attribution['costType'] = attributionData.costType!;
   if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString();
   if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!;
   if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!;

-   Adapty().updateAttribution(
-     attribution,
-     source: AdaptyAttributionSource.adjust,
-     networkUserId: adid,
-   );
+   await Adapty().updateAttribution(attribution, source: "adjust");
 } catch (e) {
   // handle the error
   } on AdaptyError catch (adaptyError) {
   // handle the error
 }

AirBridge

按照以下说明更新您的移动应用代码。完整代码示例请参阅 AirBridge 集成的 SDK 配置

 import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart';

  final deviceUUID = await Airbridge.state.deviceUUID;
  
  try {
-     final builder = AdaptyProfileParametersBuilder()
-         ..setAirbridgeDeviceId(deviceUUID);  
-     await Adapty().updateProfile(builder.build());

+     await Adapty().setIntegrationIdentifier(
+         key: "airbridge_device_id", 
+         value: deviceUUID,
+     );
  } on AdaptyError catch (adaptyError) {
     // handle the error
  } catch (e) {
     // handle the error
  }

Amplitude

按如下所示更新您的移动应用代码。完整代码示例请参阅 Amplitude 集成的 SDK 配置

 import 'package:amplitude_flutter/amplitude.dart';

 final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME");

 final deviceId = await amplitude.getDeviceId();
 final userId = await amplitude.getUserId();

 try {
-  final builder = AdaptyProfileParametersBuilder()
-     ..setAmplitudeDeviceId(deviceId)
-     ..setAmplitudeUserId(userId);
-     await adapty.updateProfile(builder.build());

+     await Adapty().setIntegrationIdentifier(
+         key: "amplitude_user_id", 
+         value: userId,
+     );
+     await Adapty().setIntegrationIdentifier(
+         key: "amplitude_device_id", 
+         value: deviceId,
+     );
  } on AdaptyError catch (adaptyError) {
      // handle the error
  } catch (e) {
      // handle the error
  }

AppMetrica

按照以下示例更新你的移动应用代码。完整代码示例请参阅 AppMetrica 集成的 SDK 配置

 import 'package:appmetrica_plugin/appmetrica_plugin.dart';

 final deviceId = await AppMetrica.deviceId;

 if (deviceId != null) {
   try {
-   final builder = AdaptyProfileParametersBuilder()
-     ..setAppmetricaDeviceId(deviceId)
-     ..setAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID");
-
-     await adapty.updateProfile(builder.build());
   
+     await Adapty().setIntegrationIdentifier(
+         key: "appmetrica_device_id", 
+         value: deviceId,
+     );
+     await Adapty().setIntegrationIdentifier(
+         key: "appmetrica_profile_id", 
+         value: "YOUR_ADAPTY_CUSTOMER_USER_ID",
+     );
    } on AdaptyError catch (adaptyError) {
      // handle the error
    } catch (e) {
      // handle the error
    }
 }

AppsFlyer

按照以下说明更新您的移动应用代码。完整代码示例请参阅 AppsFlyer 集成的 SDK 配置

 import 'package:appsflyer_sdk/appsflyer_sdk.dart';

 AppsflyerSdk appsflyerSdk = AppsflyerSdk(<YOUR_OPTIONS>);
 
 appsflyerSdk.onInstallConversionData((data) async {
     try {
         final appsFlyerUID = await appsFlyerSdk.getAppsFlyerUID();
-         await Adapty().updateAttribution(
-           data,
-           source: AdaptyAttributionSource.appsflyer,
-           networkUserId: appsFlyerUID,
-         );
+         await Adapty().setIntegrationIdentifier(
+           key: "appsflyer_id", 
+           value: appsFlyerUID,
+         );
+         
+         await Adapty().updateAttribution(data, source: "appsflyer");
     } on AdaptyError catch (adaptyError) {
         // handle the error

      } catch (e) {
          // handle the error
      }
 });

 appsflyerSdk.initSdk(
     registerConversionDataCallback: true,
     registerOnAppOpenAttributionCallback: true,
     registerOnDeepLinkingCallback: true,
 );

Branch

按照以下方式更新您的移动应用代码。完整代码示例请参阅 Branch 集成的 SDK 配置


FlutterBranchSdk.initSession().listen((data) async {
  try {
+     await Adapty().setIntegrationIdentifier(
+         key: "branch_id", 
+         value: <BRANCH_IDENTITY_ID>,
+     );
-    await Adapty().updateAttribution(data, source: AdaptyAttributionSource.branch);
+    await Adapty().updateAttribution(data, source: "branch");
  } on AdaptyError catch (adaptyError) {
      // handle the error
  } catch (e) {
      // handle the error
  }
);

Firebase 与 Google Analytics

按照以下示例更新你的移动应用代码。完整代码示例请参阅 Firebase 与 Google Analytics 集成的 SDK 配置


final appInstanceId = await FirebaseAnalytics.instance.appInstanceId;

try {
-  final builder = AdaptyProfileParametersBuilder()
-         ..setFirebaseAppInstanceId(appInstanceId);
-  await adapty.updateProfile(builder.build());

+  await Adapty().setIntegrationIdentifier(
+         key: "firebase_app_instance_id", 
+         value: appInstanceId,
+  );
} on AdaptyError catch (adaptyError) {
    // handle the error
} catch (e) {
    // handle the error
}

Mixpanel

按照以下方式更新您的移动应用代码。完整代码示例请参阅 Mixpanel 集成的 SDK 配置


final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true);
final distinctId = await mixpanel.getDistinctId();

try {
-   final builder = AdaptyProfileParametersBuilder()
-      ..setMixpanelUserId(distinctId);
-     await Adapty().updateProfile(builder.build());

+     await Adapty().setIntegrationIdentifier(
+         key: "mixpanel_user_id", 
+         value: distinctId,
+     );
} on AdaptyError catch (adaptyError) {
    // handle the error
} catch (e) {
    // handle the error
}

OneSignal

按照以下方式更新您的移动应用代码。完整代码示例请参阅 OneSignal 集成的 SDK 配置

 OneSignal.shared.setSubscriptionObserver((changes) {
     final playerId = changes.to.userId;
     if (playerId != null) {
-         final builder = 
-             AdaptyProfileParametersBuilder()
-                 ..setOneSignalPlayerId(playerId);
-                 // ..setOneSignalSubscriptionId(playerId);
          try {
-             Adapty().updateProfile(builder.build());

+             await Adapty().setIntegrationIdentifier(
+                 key: "one_signal_player_id", 
+                 value: playerId,
+             );
          } on AdaptyError catch (adaptyError) {
              // handle error
          } catch (e) {
              // handle error
          }
     }
 });

Pushwoosh

按照以下说明更新你的移动应用代码。完整代码示例请参阅 Pushwoosh 集成的 SDK 配置


final hwid = await Pushwoosh.getInstance.getHWID;

- final builder = AdaptyProfileParametersBuilder()
-         ..setPushwooshHWID(hwid);
  try {
-     await adapty.updateProfile(builder.build());

+     await Adapty().setIntegrationIdentifier(
+         key: "pushwoosh_hwid", 
+         value: hwid,
+     );
  } on AdaptyError catch (adaptyError) {
      // handle the error
  } catch (e) {
      // handle the error
  }

更新 Observer 模式实现

更新付费墙与交易的关联方式。此前,你需要使用 setVariationId 方法来分配 variationId。现在,你可以在使用新的 reportTransaction 方法记录交易时直接传入 variationId。请参阅在 Observer 模式下将付费墙与购买交易关联中的完整代码示例。

不要忘记使用 reportTransaction 方法记录交易。如果跳过此步骤,Adapty 将无法识别该交易,不会授予访问等级,不会将其纳入分析数据,也不会将其发送到集成渠道。此步骤至关重要!

 try {
-     await Adapty().setVariationId("YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID");

+     // every time when calling transaction.finish()
+     await Adapty().reportTransaction(
+         "YOUR_TRANSACTION_ID", 
+         variationId: "PAYWALL_VARIATION_ID", // optional
+     );
  } on AdaptyError catch (adaptyError) {
      // handle the error
  } catch (e) {
      // handle the error
  }