---
title: "在 Android SDK 中为远程配置付费墙获取付费墙和产品"
description: "在 Adapty Android SDK 中获取付费墙和产品，以提升用户变现效果。"
---

在展示远程配置和自定义付费墙之前，您需要先获取相关信息。请注意，本文档涉及远程配置和自定义付费墙。如需了解如何获取付费墙编辑工具自定义付费墙的相关说明，请参阅[获取付费墙编辑工具付费墙及其配置](android-get-pb-paywalls)。

:::tip

想了解 Adapty SDK 如何集成到移动应用中的真实示例？请查看我们的[示例应用](sample-apps)，其中展示了完整的配置过程，包括显示付费墙、完成购买以及其他基本功能。

:::

<details>
   <summary>在您开始在移动应用中获取付费墙和产品之前（点击展开）</summary>

   1. 在 Adapty 看板中[创建您的产品](create-product)。

2. 在 Adapty 看板中[创建付费墙并将产品添加到付费墙](create-paywall)。

3. 在 Adapty 看板中[创建版位并将付费墙添加到版位](create-placement)。

4. 在您的移动应用中[安装 Adapty SDK](sdk-installation-android)。
</details>

## 获取付费墙信息 \{#fetch-paywall-information\}

在 Adapty 中，[产品](product)是 App Store 和 Google Play 产品的组合体。这些跨平台产品被集成到付费墙中，使您能够在移动应用的特定版位中展示它们。

要展示产品，您需要使用 `getPaywall` 方法从某个[版位](placements)获取[付费墙](paywalls)。

:::important
**不要硬编码产品 ID。** 您唯一需要硬编码的 ID 是版位 ID。付费墙是远程配置的，因此产品数量和可用优惠随时可能发生变化。您的应用必须动态处理这些变化——如果今天付费墙返回两个产品，明天返回三个，则应展示全部产品，无需修改代码。
:::

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

```kotlin showLineNumbers
Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val paywall = result.value
            // the requested paywall
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
```
</TabItem>
<TabItem value="java" label="Java" default>

```java showLineNumbers
Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue();
        // the requested paywall
      
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
      
    }
});
```
</TabItem>
</Tabs>

| 参数 | 是否必填 | 描述 |
|---------|--------|-----------|
| **placementId** | 必填 | [版位](placements)的标识符。这是您在 Adapty 看板中创建版位时指定的值。 |
| **locale** | <p>可选</p><p>默认值：`en`</p> | <p>[付费墙本地化](add-remote-config-locale)的标识符。此参数应为由一个或多个子标签组成的语言代码，子标签之间用连字符（**-**）分隔。第一个子标签表示语言，第二个子标签表示地区。</p><p></p><p>示例：`en` 表示英语，`pt-br` 表示巴西葡萄牙语。</p><p></p><p>请参阅[本地化与语言代码](android-localizations-and-locale-codes)，了解更多有关语言代码及推荐使用方式的信息。</p> |
| **fetchPolicy** | 默认值：`.reloadRevalidatingCacheData` | <p>默认情况下，SDK 会尝试从服务器加载数据，若失败则返回缓存数据。我们推荐此方式，因为它可确保用户始终获得最新数据。</p><p></p><p>但是，如果您认为用户的网络连接不稳定，可以考虑使用 `.returnCacheDataElseLoad`，在缓存数据存在时优先返回缓存。在这种情况下，用户可能无法获取最新数据，但无论网络状况如何，加载速度都会更快。缓存会定期更新，因此在会话期间使用缓存以避免网络请求是安全的。</p><p></p><p>请注意，缓存在应用重启后仍然保留，仅在重新安装应用或手动清理时才会被清除。</p><p></p><p>Adapty SDK 以两层方式存储付费墙：上述定期更新的缓存和[备用付费墙](android-use-fallback-paywalls)。我们还使用 CDN 加速付费墙加载，并在 CDN 不可用时提供独立的备用服务器。该系统旨在确保您始终获取最新版本的付费墙，同时在网络连接不稳定的情况下保证可靠性。</p> |
| **loadTimeout** | 默认值：5 秒 | <p>此值限制该方法的超时时间。若超时，将返回缓存数据或本地备用数据。</p><p></p><p>请注意，在极少数情况下，该方法可能比 `loadTimeout` 中指定的时间稍晚超时，因为该操作在底层可能包含多个不同请求。</p> |

不要硬编码产品 ID！由于付费墙是远程配置的，可用产品、产品数量以及特殊优惠（如免费试用）可能随时发生变化。请确保您的代码能够处理这些情况。  
例如，如果您最初获取到 2 个产品，您的应用应展示这 2 个产品。但如果之后获取到 3 个产品，您的应用应展示全部 3 个，无需修改任何代码。唯一需要硬编码的是版位 ID。

响应参数：

| 参数 | 描述 |
| :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Paywall | 一个 [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) 对象，包含：产品 ID 列表、付费墙标识符、远程配置及其他若干属性。 |

## 获取产品 \{#fetch-products\}

获取付费墙后，您可以查询与之对应的产品数组：

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

```kotlin showLineNumbers
Adapty.getPaywallProducts(paywall) { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val products = result.value
            // the requested products
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
```
</TabItem>
<TabItem value="java" label="Java" default>

```java showLineNumbers
Adapty.getPaywallProducts(paywall, result -> {
    if (result instanceof AdaptyResult.Success) {
        List<AdaptyPaywallProduct> products = ((AdaptyResult.Success<List<AdaptyPaywallProduct>>) result).getValue();
        // the requested products
      
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
      
    }
});
```
</TabItem>
</Tabs>

响应参数：

| 参数 | 描述 |
| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Products | [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) 对象列表，包含：产品标识符、产品名称、价格、货币、订阅时长及其他若干属性。 |

在实现自定义付费墙设计时，您可能需要访问 [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) 对象中的这些属性。以下列出了最常用的属性，完整的属性列表请参阅链接文档。

| 属性 | 描述 |
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Title（标题）** | 要展示产品标题，请使用 `product.localizedTitle`。请注意，本地化基于用户所选的商店国家/地区，而非设备本身的语言环境。 |
| **Price（价格）** | 要展示本地化价格，请使用 `product.price.localizedString`。该本地化基于设备的语言环境信息。您也可以通过 `product.price.amount` 以数字形式访问价格，该值以当地货币表示。要获取对应的货币符号，请使用 `product.price.currencySymbol`。 |
| **Subscription Period（订阅周期）** | 要展示订阅周期（例如：周、月、年等），请使用 `product.subscriptionDetails?.localizedSubscriptionPeriod`。该本地化基于设备的语言环境。要以编程方式获取订阅周期，请使用 `product.subscriptionDetails?.subscriptionPeriod`。通过该属性可以访问 `unit` 枚举以获取时长单位（即 DAY、WEEK、MONTH、YEAR 或 UNKNOWN）。`numberOfUnits` 值表示周期单位的数量。例如，对于季度订阅，`unit` 属性值为 `MONTH`，`numberOfUnits` 属性值为 `3`。 |
| **Introductory Offer（新用户优惠）** | 要展示徽标或其他指示器表明订阅包含新用户优惠，请查看 `product.subscriptionDetails?.introductoryOfferPhases` 属性。这是一个最多可包含两个折扣阶段的列表：免费试用阶段和优惠价格阶段。每个阶段对象包含以下实用属性：<br/>• `paymentMode`：枚举值，包含 `FREE_TRIAL`、`PAY_AS_YOU_GO`、`PAY_UPFRONT` 和 `UNKNOWN`。免费试用属于 `FREE_TRIAL` 类型。<br/>• `price`：折扣价格（数字）。免费试用时，此处应为 `0`。<br/>• `localizedNumberOfPeriods`：使用设备语言环境本地化的字符串，描述优惠时长。例如，三天试用优惠在此字段显示为 `3 days`。<br/>• `subscriptionPeriod`：您也可以通过此属性获取优惠周期的单独详情，其使用方式与上一节中描述的订阅周期相同。<br/>• `localizedSubscriptionPeriod`：针对用户语言环境格式化的折扣订阅周期。 |

## 使用默认目标受众付费墙加速付费墙获取 \{#speed-up-paywall-fetching-with-default-audience-paywall\}

通常情况下，付费墙几乎可以即时获取，无需担心速度问题。但是，如果您拥有大量目标受众和付费墙，且用户网络连接较弱，获取付费墙可能需要比预期更长的时间。在这种情况下，您可能希望展示默认付费墙，以确保良好的用户体验，而不是不显示任何付费墙。

为解决这一问题，您可以使用 `getPaywallForDefaultAudience` 方法，该方法为 **All Users** 目标受众获取指定版位的付费墙。但请务必了解，推荐的方式是使用 `getPaywall` 方法获取付费墙，详见上文[获取付费墙信息](fetch-paywalls-and-products-android#fetch-paywall-information)部分。

:::warning
为何我们推荐使用 `getPaywall`

`getPaywallForDefaultAudience` 方法存在以下几个重要缺点：

- **潜在的向后兼容性问题**：如果您需要为不同的应用版本（当前版本和未来版本）展示不同的付费墙，可能会面临挑战。您要么必须设计支持当前（旧版）版本的付费墙，要么接受当前（旧版）版本的用户可能遇到付费墙无法渲染的问题。
- **失去精准定向**：所有用户将看到为 **All Users** 目标受众设计的同一个付费墙，这意味着您将失去个性化定向能力（包括基于国家/地区、营销归因或您自定义属性的定向）。

如果您愿意接受这些缺点以换取更快的付费墙获取速度，请按以下方式使用 `getPaywallForDefaultAudience` 方法。否则，请继续使用[上文](#fetch-paywall-information)描述的 `getPaywall`。
:::

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

```kotlin showLineNumbers
Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val paywall = result.value
            // the requested paywall
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
```
</TabItem>
<TabItem value="java" label="Java" default>

```java showLineNumbers
Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue();
        // the requested paywall
      
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
      
    }
});
```
</TabItem>
</Tabs>

:::note
`getPaywallForDefaultAudience` 方法从 Android SDK 2.11.3 版本开始可用。
:::

| 参数 | 是否必填 | 描述 |
|---------|--------|-----------|
| **placementId** | 必填 | [版位](placements)的标识符。这是您在 Adapty 看板中创建版位时指定的值。 |
| **locale** | <p>可选</p><p>默认值：`en`</p> | <p>[付费墙本地化](add-remote-config-locale)的标识符。此参数应为由一个或多个子标签组成的语言代码，子标签之间用连字符（**-**）分隔。第一个子标签表示语言，第二个子标签表示地区。</p><p></p><p>示例：`en` 表示英语，`pt-br` 表示巴西葡萄牙语。</p><p></p><p>请参阅[本地化与语言代码](android-localizations-and-locale-codes)，了解更多有关语言代码及推荐使用方式的信息。</p> |
| **fetchPolicy** | 默认值：`.reloadRevalidatingCacheData` | <p>默认情况下，SDK 会尝试从服务器加载数据，若失败则返回缓存数据。我们推荐此方式，因为它可确保用户始终获得最新数据。</p><p></p><p>但是，如果您认为用户的网络连接不稳定，可以考虑使用 `.returnCacheDataElseLoad`，在缓存数据存在时优先返回缓存。在这种情况下，用户可能无法获取最新数据，但无论网络状况如何，加载速度都会更快。缓存会定期更新，因此在会话期间使用缓存以避免网络请求是安全的。</p><p></p><p>请注意，缓存在应用重启后仍然保留，仅在重新安装应用或手动清理时才会被清除。</p> |