---
title: "将 Adapty Flutter SDK 迁移至 v4.1"
description: "迁移至 Adapty Flutter SDK v4.1：显式启用 Adapty Attribution、采用重命名后的外部归因 API、重新下载备用文件，以及处理 App Store 推广购买。"
---

> **AI agents**: to search Adapty docs faster and with fewer tokens, install the Adapty skill. Claude Code (self-updating via plugin): `claude plugin marketplace add adaptyteam/adapty-skills && claude plugin install adapty-skills@adapty` — other tools: `npx skills add adaptyteam/adapty-skills --all`

Adapty Flutter SDK 4.1 更改了 Adapty Attribution 的启用方式，重命名了外部归因 API，并更改了备用文件格式。此外，它还将 App Store 推广的应用内购买交由您的应用处理，并新增了一种在关闭流程视图后保持其存活的方法。

:::warning
重命名的 API 是硬性中断。旧名称已被彻底移除——没有任何已废弃的别名可以过渡。针对 4.0.x 编译的代码在 4.1 上将无法通过编译，直到你将下方列出的每一个调用处都重命名为止。
:::

如果你还在使用 3.x，请先参阅[迁移到 v4.0](migration-to-flutter-sdk-v4)，再按照本指南操作。

## 快速参考 \{#quick-reference\}

| v4.0 | v4.1 |
|---|---|
| Adapty Attribution 默认启用 | Adapty Attribution 默认禁用；通过 `withAdaptyAttributionEnabled(true)` 启用 |
| `Adapty().updateAttribution(attribution, source: source)` | `Adapty().updateExternalAttribution(attribution, provider: provider)` |
| `AdaptyAttributionSource` | `AdaptyExternalAttributionProvider`，新增 `custom` 值 |
| `AdaptyProfile.appliedAttributionSources` | `AdaptyProfile.appliedExternalAttributionProviders` |
| 已为 4.0 下载备用文件 | 新备用文件格式；请重新下载文件 |
| 推广应用内购买自动完成 | 由您的应用在 `didReceivePromotedPurchaseStream` 中完成 |
| `dismissFlowView(view)` 始终释放视图 | `destroy: false` 保留视图以便再次呈现 |

购买、用户画像及流程展示相关 API 均保持不变。

## 安装 \{#installation\}

在 `pubspec.yaml` 中将 `adapty_flutter` 更新至 v4.1：

```yaml showLineNumbers title="pubspec.yaml"
dependencies:
  adapty_flutter: 4.1.0
```

如果你的应用使用 [Kids Mode](kids-mode-flutter)，请改用 `adapty_flutter_kids`：

```yaml showLineNumbers title="pubspec.yaml"
dependencies:
  adapty_flutter_kids: 4.1.0
```

环境要求与 4.0 相同：**Flutter 3.32.0**（Dart 3.8.0）和 **iOS 15.0**。完整安装步骤请参阅 [安装 Adapty SDK](sdk-installation-flutter)。

4.1 将原生 iOS SDK 固定到 4.1.3 版本，将原生 Android SDK 固定到 4.1.1 版本。iOS 版本还修复了流程分析事件中的数值参数问题：此前，所有 `0` 和 `1` 都会以 `false` 和 `true` 的形式传递给 `flowViewDidReceiveAnalyticEvent`。

## ⚠️ Adapty 归因功能默认已禁用 \{#adapty-attribution-is-disabled-by-default\}

:::warning
如果你升级到 SDK 4.1 且未主动启用该功能，[Adapty 归因](user-acquisition)将悄无声息地停止工作——新安装将不再被记录，且不会有任何警告提示。
:::

在 4.0 及更早版本中，SDK 会自动为 [Adapty 归因](user-acquisition) 注册安装记录。从 4.1 开始，该功能默认关闭：SDK 不再注册安装，`onUpdateInstallationDetailsSuccessStream` 和 `onUpdateInstallationDetailsFailStream` 不会触发任何事件，`getCurrentInstallationStatus` 返回 `AdaptyInstallationStatusNotAvailable`。

如果你使用 Adapty 归因功能，请在配置 SDK 时启用它：

```diff showLineNumbers
  await Adapty().activate(
-   configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY'),
+   configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY')
+     ..withAdaptyAttributionEnabled(true),
  );
```

如果你不使用 Adapty Attribution，则无需任何更改。

## 重命名外部归因 API \{#renamed-external-attribution-apis\}

用于从外部提供商（Adjust、AppsFlyer、Branch、Tenjin 或自定义提供商）传递归因数据的 API 已重命名，以与原生 SDK 保持一致。

### updateAttribution → updateExternalAttribution

该方法已重命名，其 `source` 参数也重命名为 `provider`。该参数现在接受 `AdaptyExternalAttributionProvider` 而非字符串，归因数据仍为 map 格式：

```diff showLineNumbers
- await Adapty().updateAttribution(attribution, source: 'adjust');
+ await Adapty().updateExternalAttribution(attribution, provider: AdaptyExternalAttributionProvider.adjust);
```

### AdaptyAttributionSource → AdaptyExternalAttributionProvider

该 provider 类型已重命名。它仍然是对字符串的开放式封装——预定义值为 `appleAds`、`adjust`、`appsflyer`、`branch`、`tenjin`，以及新增的 `custom`（用于 Adapty 未直接集成的 provider）。你也可以用任意字符串构造一个，因此即使 Adapty 后续新增 provider，也无需更新 SDK：

```dart showLineNumbers
final provider = AdaptyExternalAttributionProvider('my_provider');
```

### AdaptyProfile.appliedAttributionSources → appliedExternalAttributionProviders

列出已应用到用户画像的归因提供商的属性已重命名，其元素类型也随之更改：

```diff showLineNumbers
- if (profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) {
+ if (profile.appliedExternalAttributionProviders.contains(AdaptyExternalAttributionProvider.appleAds)) {
      // Apple Ads attribution has been applied
  }
```

序列化后的用户画像字段仍保留名称 `applied_attribution_sources`，因此读取原始用户画像的后端无需任何更改。读取该属性的代码则需要更新——详见[展示 Apple Ads 定向付费墙](flutter-show-aa-targeted-paywall)。

## 备用文件 \{#fallback-files\}

[备用文件](fallback-flows) 的格式在 SDK 4.1 中发生了变化。请从 **[Placements](https://app.adapty.io/placements)** > **Fallbacks** 重新下载该文件并将其打包到应用中，即使你已经为 4.0 下载过。

:::warning
跳过此步骤不会产生构建错误。但如果跳过，SDK 将拒绝使用过期的文件，导致所有版位失去其备用付费墙。
:::

## ⚠️ 应用商店推广内购现在需要您的应用响应 \{#promoted-in-app-purchases-now-wait-for-your-app\}

:::warning
这是一项行为变更，而非可以择机采用的新功能。在 4.0 版本中，[在 App Store 产品页面推广的内购](flutter-making-purchases#promoted-in-app-purchases-from-the-app-store)会自动完成。在 4.1 版本中，只有当您的应用监听相关事件时，购买才会完成。若您在未添加以下代码的情况下发布 4.1 版本，这些购买将无法完成——App Store 会将产品交给您的应用，但之后什么都不会发生。
:::

在 4.0 版本中，Adapty 会像处理普通交易一样记录促销购买，你的应用无法对其进行拦截。4.1 版本赋予了你的应用这一控制权，同时也带来了相应的责任——你需要自行完成购买流程。

订阅 `didReceivePromotedPurchaseStream`，并将产品传递给 `makePromotedPurchase`：

```dart showLineNumbers
Adapty().didReceivePromotedPurchaseStream.listen((product) async {
  try {
    final result = await Adapty().makePromotedPurchase(product: product);
    // process the purchase result
  } on AdaptyError catch (e) {
    // handle the error
  }
});
```

在应用启动时、`activate` 执行完成后立即订阅，以免错过促销购买事件。该流是广播流，不会重放历史数据：如果在没有监听器的情况下发送了产品，该次购买就会丢失。

`makePromotedPurchase` 不接受任何购买参数，因为促销产品来自 App Store 而非付费墙，不携带付费墙上下文。它返回与 `makePurchase` 相同的 `AdaptyPurchaseResult`。

:::warning
该流基于 StoreKit 2 构建，需要 **iOS 16.4** 或更高版本。低于 iOS 16.4 的系统以及 Android 平台上，该流永远不会触发。
:::

如果推广产品附带订阅优惠，SDK 将在购买时自动应用该优惠。此优惠从 App Store 购买意图中读取，iOS 18.0 及更高版本支持此功能。在 iOS 16.4–17.x 上，购买将以原价进行。

## 关闭流程视图后保持其存活状态 \{#keep-a-flow-view-alive-after-dismissing-it\}

`AdaptyUI().dismissFlowView` 和 `AdaptyUIFlowView.dismiss` 接受一个 `destroy` 参数：

```dart showLineNumbers
await AdaptyUI().dismissFlowView(view, destroy: false);
```

该参数默认值为 `true`，与之前一样会释放视图。设置为 `destroy: false` 时，视图将保持存活，你可以再次展示它，用户会回到离开时的页面，且流程积累的状态也会保留。

以这种方式保留的视图会一直存在，直到你使用 `destroy: true` 将其关闭。展示已释放的视图会失败，因此如需再次显示该流程，请重新调用 `createFlowView`。

## hasViewConfiguration

`AdaptyFlow.hasViewConfiguration` 现在还要求流程携带 UI schema，因此只有 AdaptyUI 能够渲染的流程才会返回 `true`。如果一个流程到达您的应用时没有携带 schema，现在会返回 `false`，而 4.0 版本会返回 `true`。请参阅[获取视图配置](flutter-get-pb-paywalls#fetch-the-view-configuration)。