在 Android SDK 中以 Observer 模式展示流程
安装 AI Agent 工具
在你的 AI 编程工具中完成整个 Adapty SDK 集成。 了解更多
可安装到任何支持技能的 AI 工具。之后更新请运行 npx skills update。
这些技能涵盖 SDK 集成、构建 flow 和 paywall、发布前审查、placement 迁移等。用日常语言描述任务,你的 AI Agent 会自动选择合适的技能。
如果你使用 Observer 模式,则需要自行处理购买逻辑。但你可以将付费墙 UI 的展示工作交给 Flow & Paywall Builder 来完成。
在编辑工具中设计好界面后,Adapty SDK 会原生渲染该界面。你可以随时更新文案、布局和定价,无需发布新版本。当用户点击购买按钮时,SDK 会调用你的代码完成购买。
本指南介绍如何展示该界面并处理购买回调。如果由 Adapty 代为完成购买,请参阅展示流程与付费墙。
开始之前
你需要:
- Adapty Android SDK v4 或更高版本:早期版本无法渲染流程。如需将现有应用从 v3 迁移,请参阅迁移指南。
- 将
observerMode设置为true:请参阅 Android SDK 安装指南。 - 初始商店集成:配置 Adapty 与 Google Play 的集成。
- 已发布且包含产品的流程:在流程与付费墙编辑工具中构建,并为其分配产品。
- 流程版位:创建版位并将您的流程分配到该版位。
- 在应用中获取流程:在展示流程之前,获取流程及其配置。
实现
- 实现
AdaptyUiObserverModeHandler。
当用户发起购买时,onPurchaseInitiated 事件会通知你。你可以在此回调中触发自定义购买流程:
val observerModeHandler =
AdaptyUiObserverModeHandler { product, onStartPurchase, onFinishPurchase ->
onStartPurchase()
yourBillingClient.makePurchase(
product,
onSuccess = { purchase ->
onFinishPurchase()
//handle success
},
onError = {
onFinishPurchase()
//handle error
},
onCancel = {
onFinishPurchase()
//handle cancel
}
)
} AdaptyUiObserverModeHandler observerModeHandler = (product, onStartPurchase, onFinishPurchase) -> {
onStartPurchase.invoke();
yourBillingClient.makePurchase(
product,
purchase -> {
onFinishPurchase.invoke();
//handle success
},
error -> {
onFinishPurchase.invoke();
//handle error
},
() -> { //cancellation
onFinishPurchase.invoke();
//handle cancel
}
);
}; 要在 Observer 模式下处理恢复操作,请重写 getRestoreHandler()。默认情况下,它返回 null,即使用 Adapty 内置的 Adapty.restorePurchases() 流程。如需提供自定义的恢复实现:
val observerModeHandler = object : AdaptyUiObserverModeHandler {
override fun onPurchaseInitiated(
product: AdaptyPaywallProduct,
onStartPurchase: AdaptyUiObserverModeHandler.PurchaseStartCallback,
onFinishPurchase: AdaptyUiObserverModeHandler.PurchaseFinishCallback,
) {
// the same body as the purchase example above
}
override fun getRestoreHandler() =
AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore ->
onStartRestore()
yourBillingClient.restorePurchases(
onSuccess = { restoredPurchases ->
onFinishRestore()
//handle successful restore
},
onError = {
onFinishRestore()
//handle error
}
)
}
} AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() {
@Override
public void onPurchaseInitiated(
AdaptyPaywallProduct product,
PurchaseStartCallback onStartPurchase,
PurchaseFinishCallback onFinishPurchase
) {
// the same body as the purchase example above
}
@Override
public RestoreHandler getRestoreHandler() {
return (onStartRestore, onFinishRestore) -> {
onStartRestore.invoke();
yourBillingClient.restorePurchases(
restoredPurchases -> {
onFinishRestore.invoke();
//handle successful restore
},
error -> {
onFinishRestore.invoke();
//handle error
}
);
};
}
}; 请记得调用以下回调,以便将购买或恢复操作的状态通知给 AdaptyUI。这对于正确的流程行为(例如显示加载动画)是必要的:
| 回调 | 描述 |
|---|---|
| onStartPurchase() | 应调用此回调以通知 AdaptyUI 购买已开始。 |
| onFinishPurchase() | 应调用此回调以通知 AdaptyUI 购买已完成。 |
| onStartRestore() | 可选。可调用此回调以通知 AdaptyUI 恢复购买已开始。 |
| onFinishRestore() | 可选。可调用此回调以通知 AdaptyUI 恢复购买已完成。 |
- 要在设备屏幕上显示可视化流程,您必须先对其进行配置。
为此,请调用方法 AdaptyUI.getFlowView() 或直接创建 AdaptyFlowView:
val flowView = AdaptyUI.getFlowView(
activity,
flowConfiguration,
products,
eventListener,
insets,
customAssets,
tagResolver,
timerResolver,
observerModeHandler,
) val flowView =
AdaptyFlowView(activity) // or retrieve it from xml
...
with(flowView) {
showFlow(
flowConfiguration,
products,
eventListener,
insets,
customAssets,
tagResolver,
timerResolver,
observerModeHandler,
)
} AdaptyFlowView flowView = AdaptyUI.getFlowView(
activity,
flowConfiguration,
products,
eventListener,
insets,
customAssets,
tagResolver,
timerResolver,
observerModeHandler
); AdaptyFlowView flowView =
new AdaptyFlowView(activity); //add to the view hierarchy if needed, or you receive it from xml
...
flowView.showFlow(flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler); <com.adapty.ui.AdaptyFlowView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" /> 成功创建视图后,即可将其添加到视图层次结构并显示。
使用以下可组合函数:
AdaptyFlowScreen(
flowConfiguration,
products,
eventListener,
insets,
customAssets,
tagResolver,
timerResolver,
observerModeHandler,
) 请求参数:
| 参数 | 是否必填 | 描述 |
|---|---|---|
| flowConfiguration | 必填 | 提供一个包含流程视觉详情的 AdaptyUI.FlowConfiguration 对象。使用 AdaptyUI.getFlowConfiguration(flow) 方法加载。详情请参阅 获取视图配置。 |
| products | 选填 | 提供一个 AdaptyPaywallProduct 数组,以优化产品在屏幕上的展示时机。若传入 null,AdaptyUI 将自动获取所需产品。 |
| eventListener | 选填 | 提供一个 AdaptyFlowEventListener 以监听流程事件。建议继承 AdaptyFlowDefaultEventListener 以简化使用。详情请参阅 处理流程与付费墙事件。 |
| insets | 选填 | Insets 是流程周围的间距,用于防止可点击元素被系统栏遮挡。默认值:Unspecified,表示由 Adapty 自动调整 insets。参见 修改流程 insets。 |
| customAssets | 选填 | 传入一个 AdaptyCustomAssets 对象,以在运行时替换流程中的图片和视频。详情请参阅 自定义资源。 |
| tagResolver | 选填 | 使用 AdaptyUiTagResolver 解析流程文本中的自定义标签。该解析器接收标签参数并将其解析为对应的字符串。 |
| observerModeHandler | Observer 模式必填 | 您在上一步骤中实现的 AdaptyUiObserverModeHandler。 |
不要忘记将付费墙与购买交易关联。否则,Adapty 将无法确定购买的来源流程。
开始展示付费墙之前(点击展开)
- 在 Adapty 看板中完成初始集成,包括与 Google Play 的集成和与 App Store 的集成。
2. 安装并配置 Adapty SDK,确保将
observerMode参数设置为true。请参阅针对 Android 的框架专项说明。 3. 在 Adapty 看板中创建产品。 4. 在 Adapty 看板中配置付费墙并为其分配产品,然后使用付费墙编辑工具对其进行自定义。 5. 在 Adapty 看板中创建版位并将付费墙分配给相应版位。 6. 在移动应用代码中获取付费墙编辑工具的付费墙及其配置。
- 实现
AdaptyUiObserverModeHandler。
onPurchaseInitiated 事件会通知你用户已发起购买。你可以在此回调中触发自定义购买流程:
Adapty Android SDK 3.15.0 之前的版本还会将付费墙和付费墙视图传入此回调。升级到 3.15.0 或更高版本时,请删除这两个参数。
val observerModeHandler =
AdaptyUiObserverModeHandler { product, onStartPurchase, onFinishPurchase ->
onStartPurchase()
yourBillingClient.makePurchase(
product,
onSuccess = { purchase ->
onFinishPurchase()
//handle success
},
onError = {
onFinishPurchase()
//handle error
},
onCancel = {
onFinishPurchase()
//handle cancel
}
)
} AdaptyUiObserverModeHandler observerModeHandler = (product, onStartPurchase, onFinishPurchase) -> {
onStartPurchase.invoke();
yourBillingClient.makePurchase(
product,
purchase -> {
onFinishPurchase.invoke();
//handle success
},
error -> {
onFinishPurchase.invoke();
//handle error
},
() -> { //cancellation
onFinishPurchase.invoke();
//handle cancel
}
);
}; 要在观察者模式下处理恢复操作,请重写 getRestoreHandler()。默认情况下它返回 null,即使用 Adapty 内置的 Adapty.restorePurchases() 流程。如需提供自定义恢复实现:
val observerModeHandler = object : AdaptyUiObserverModeHandler {
override fun onPurchaseInitiated(
product: AdaptyPaywallProduct,
onStartPurchase: AdaptyUiObserverModeHandler.PurchaseStartCallback,
onFinishPurchase: AdaptyUiObserverModeHandler.PurchaseFinishCallback,
) {
// the same body as the purchase example above
}
override fun getRestoreHandler() =
AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore ->
onStartRestore()
yourBillingClient.restorePurchases(
onSuccess = { restoredPurchases ->
onFinishRestore()
//handle successful restore
},
onError = {
onFinishRestore()
//handle error
}
)
}
} AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() {
@Override
public void onPurchaseInitiated(
AdaptyPaywallProduct product,
PurchaseStartCallback onStartPurchase,
PurchaseFinishCallback onFinishPurchase
) {
// the same body as the purchase example above
}
@Override
public RestoreHandler getRestoreHandler() {
return (onStartRestore, onFinishRestore) -> {
onStartRestore.invoke();
yourBillingClient.restorePurchases(
restoredPurchases -> {
onFinishRestore.invoke();
//handle successful restore
},
error -> {
onFinishRestore.invoke();
//handle error
}
);
};
}
}; 请记得调用以下回调,以便将购买或恢复流程通知给 AdaptyUI。这对于正确的付费墙行为(例如显示加载动画)是必要的:
| 回调 | 描述 |
|---|---|
| onStartPurchase() | 应调用此回调以通知 AdaptyUI 购买已开始。 |
| onFinishPurchase() | 应调用此回调以通知 AdaptyUI 购买已完成。 |
| onStartRestore() | 可选。可调用此回调以通知 AdaptyUI 恢复操作已开始。 |
| onFinishRestore() | 可选。可调用此回调以通知 AdaptyUI 恢复操作已完成。 |
- 要在设备屏幕上显示可视化付费墙,必须先对其进行配置。
为此,调用 AdaptyUI.getPaywallView() 方法,或直接创建 AdaptyPaywallView:
val paywallView = AdaptyUI.getPaywallView(
activity,
viewConfiguration,
products,
eventListener,
personalizedOfferResolver,
tagResolver,
timerResolver,
observerModeHandler,
) val paywallView =
AdaptyPaywallView(activity) // or retrieve it from xml
...
with(paywallView) {
showPaywall(
viewConfiguration,
products,
eventListener,
personalizedOfferResolver,
tagResolver,
timerResolver,
observerModeHandler,
)
} AdaptyPaywallView paywallView = AdaptyUI.getPaywallView(
activity,
viewConfiguration,
products,
eventListener,
personalizedOfferResolver,
tagResolver,
timerResolver,
observerModeHandler
); AdaptyPaywallView paywallView =
new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml
...
paywallView.showPaywall(viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler); <com.adapty.ui.AdaptyPaywallView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" /> 视图成功创建后,你可以将其添加到视图层级并显示。
使用以下可组合函数:
AdaptyPaywallScreen(
viewConfiguration,
products,
eventListener,
personalizedOfferResolver,
tagResolver,
timerResolver,
) 请求参数:
| 参数 | 是否必填 | 描述 |
|---|---|---|
| Products | 可选 | 提供一个 AdaptyPaywallProduct 数组,以优化产品在屏幕上的显示时机。如果传入 null,AdaptyUI 将自动获取所需产品。 |
| ViewConfiguration | 必填 | 提供一个包含付费墙视觉详情的 AdaptyViewConfiguration 对象。使用 Adapty.getViewConfiguration(paywall) 方法加载。详情请参阅获取付费墙的视觉配置。 |
| EventListener | 可选 | 提供一个 AdaptyUiEventListener 以监听付费墙事件。建议继承 AdaptyUiDefaultEventListener 以简化使用。详情请参阅处理付费墙事件。 |
| PersonalizedOfferResolver | 可选 | 如需标注个性化定价(了解更多),请实现 AdaptyUiPersonalizedOfferResolver,并传入自定义逻辑,将 AdaptyPaywallProduct 映射为 true(价格已个性化)或 false。 |
| TagResolver | 可选 | 使用 AdaptyUiTagResolver 解析付费墙文本中的自定义标签。该解析器接收标签参数并将其解析为对应字符串。详情请参阅付费墙编辑工具中的自定义标签相关内容。 |
| ObserverModeHandler | Observer 模式下必填 | 您在上一步中实现的 AdaptyUiObserverModeHandler。 |
| variationId | 必填 | 实验变体的字符串标识符。可通过 AdaptyPaywall 对象的 variationId 属性获取。 |
| transaction | 必填 | iOS,StoreKit 1: iOS,StoreKit 2:Transaction 对象。 Android:购买记录的字符串标识符( |
开始展示付费墙前(点击展开)
- 在 Adapty 看板中完成与 Google Play 和 App Store 的初始集成。
- 安装并配置 Adapty SDK,确保将
observerMode参数设置为true。请参阅各框架的具体说明:Android、React Native、Flutter 和 Unity。 - 在 Adapty 看板中创建产品。
- 在 Adapty 看板中配置付费墙并为其分配产品,并使用付费墙编辑工具进行自定义。
- 在 Adapty 看板中创建版位并为其分配付费墙。
- 在移动应用代码中获取付费墙编辑工具的付费墙及其配置。
- 实现
AdaptyUiObserverModeHandler。AdaptyUiObserverModeHandler的回调函数(onPurchaseInitiated)会在用户发起购买时通知你。你可以在此回调中触发自定义购买流程,示例如下:
val observerModeHandler =
AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase ->
onStartPurchase()
yourBillingClient.makePurchase(
product,
onSuccess = { purchase ->
onFinishPurchase()
//handle success
},
onError = {
onFinishPurchase()
//handle error
},
onCancel = {
onFinishPurchase()
//handle cancel
}
)
} AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> {
onStartPurchase.invoke();
yourBillingClient.makePurchase(
product,
purchase -> {
onFinishPurchase.invoke();
//handle success
},
error -> {
onFinishPurchase.invoke();
//handle error
},
() -> { //cancellation
onFinishPurchase.invoke();
//handle cancel
}
);
}; 此外,请记得调用这些 AdaptyUI 回调。这对于付费墙的正常运行至关重要,例如显示加载动画等:
| Kotlin 中的回调 | Java 中的回调 | 描述 |
|---|---|---|
| onStartPurchase() | onStartPurchase.invoke() | 应调用此回调以通知 AdaptyUI 购买已开始。 |
| onFinishPurchase() | onFinishPurchase.invoke() | 应调用此回调以通知 AdaptyUI 购买已成功完成、未完成或已取消。 |
- 要显示可视化付费墙,您必须先对其进行初始化。为此,请调用
AdaptyUI.getPaywallView()方法,或直接创建AdaptyPaywallView:
val paywallView = AdaptyUI.getPaywallView(
activity,
viewConfiguration,
products,
AdaptyPaywallInsets.of(topInset, bottomInset),
eventListener,
personalizedOfferResolver,
tagResolver,
observerModeHandler,
)
//======= OR =======
val paywallView =
AdaptyPaywallView(activity) // or retrieve it from xml
...
with(paywallView) {
setEventListener(eventListener)
setObserverModeHandler(observerModeHandler)
showPaywall(
viewConfiguration,
products,
AdaptyPaywallInsets.of(topInset, bottomInset),
personalizedOfferResolver,
tagResolver,
)
} AdaptyPaywallView paywallView = AdaptyUI.getPaywallView(
activity,
viewConfiguration,
products,
AdaptyPaywallInsets.of(topInset, bottomInset),
eventListener,
personalizedOfferResolver,
tagResolver,
observerModeHandler
);
//======= OR =======
AdaptyPaywallView paywallView =
new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml
...
paywallView.setEventListener(eventListener);
paywallView.setObserverModeHandler(observerModeHandler);
paywallView.showPaywall(viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver); <com.adapty.ui.AdaptyPaywallView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" /> 视图成功创建后,您可以将其添加到视图层级并显示出来。
请求参数:
| 参数 | 是否必填 | 描述 |
|---|---|---|
| Products | 可选 | 提供一个 AdaptyPaywallProduct 数组,以优化产品在屏幕上的显示时机。如果传入 null,AdaptyUI 将自动获取所需产品。 |
| ViewConfiguration | 必填 | 提供一个包含付费墙视觉细节的 AdaptyViewConfiguration 对象。使用 Adapty.getViewConfiguration(paywall) 方法加载。详情请参阅获取付费墙的视觉配置主题。 |
| Insets | 必填 | 定义一个 AdaptyPaywallInsets 对象,包含系统栏遮挡区域的信息,为内容创建垂直边距。如果状态栏和导航栏均未遮挡 AdaptyPaywallView,请传入 AdaptyPaywallInsets.NONE。在系统栏遮挡部分 UI 的全屏模式下,请按表格下方的说明获取 insets。 |
| EventListener | 可选 | 提供一个 AdaptyUiEventListener 以监听付费墙事件。推荐继承 AdaptyUiDefaultEventListener 以简化使用。详情请参阅处理付费墙事件主题。 |
| PersonalizedOfferResolver | 可选 | 如需标注个性化定价(了解更多),请实现 AdaptyUiPersonalizedOfferResolver 并传入您自己的逻辑,将 AdaptyPaywallProduct 映射为 true(若该产品价格为个性化定价),否则映射为 false。 |
| TagResolver | 可选 | 使用 AdaptyUiTagResolver 解析付费墙文本中的自定义标签。该解析器接收一个标签参数并将其解析为对应的字符串。详情请参阅付费墙编辑工具中的自定义标签主题。 |
| ObserverModeHandler | Observer 模式必填 | 您在上一步中实现的 AdaptyUiObserverModeHandler。 |
| variationId | 必填 | 实验变体的字符串标识符。可通过 AdaptyPaywall 对象的 variationId 属性获取。 |
| transaction | 必填 | iOS,StoreKit 1: iOS,StoreKit 2:Transaction 对象。 Android:购买记录的字符串标识符( |
对于系统栏覆盖部分 UI 的全屏模式,请按以下方式获取 insets:
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
//create extension function
fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) {
ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
ViewCompat.setOnApplyWindowInsetsListener(this, null)
action(systemBarInsets)
insets
}
}
//and then use it with the view
paywallView.onReceiveSystemBarsInsets { insets ->
val paywallInsets = AdaptyPaywallInsets.of(insets.top, insets.bottom)
paywallView.setEventListener(eventListener)
paywallView.setObserverModeHandler(observerModeHandler)
paywallView.showPaywall(viewConfig, products, paywallInsets, personalizedOfferResolver, tagResolver)
} import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
...
ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> {
Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
ViewCompat.setOnApplyWindowInsetsListener(paywallView, null);
AdaptyPaywallInsets paywallInsets =
AdaptyPaywallInsets.of(systemBarInsets.top, systemBarInsets.bottom);
paywallView.setEventListener(eventListener);
paywallView.setObserverModeHandler(observerModeHandler);
paywallView.showPaywall(viewConfiguration, products, paywallInsets, personalizedOfferResolver, tagResolver);
return insets;
}); 返回值:
| 对象 | 描述 |
|---|---|
AdaptyPaywallView | 表示所请求的付费墙界面的对象。 |
不要忘记将付费墙关联到购买交易。否则,Adapty 将无法确定该购买来源于哪个付费墙。