Передача данных во флоу в Android SDK
Кастомный тег — это переменная, значение которой задаётся вашим приложением. Когда в настройках переменной выбрано Value comes from outside the app, приложение может передать её значение через Adapty SDK. Например, текстовый элемент содержит «Coins:» и кастомный тег. Если приложение передаёт для этого тега значение «120», пользователь видит «Coins: 120».
Прежде чем начать
Вам необходим Adapty SDK версии 4 или выше. Версии ниже v4 не отображают флоу.
Добавьте пользовательские теги во флоу
Чтобы отображать значения из вашего приложения во флоу, настройте кастомные теги в билдере:
-
Создайте кастомный тег для каждого значения, которое передаёт ваше приложение.
-
Запишите полное имя каждого тега, включая его группу. Именно под этим именем код вашего приложения передаёт каждое значение. Например, если группа
userсодержит тегstreak, полное имя тега —user.streak.
Передача пользовательских значений тегов
Создайте AdaptyUiTagResolver и передайте его в параметр tagResolver метода AdaptyUI.getFlowView. SDK вызывает резолвер с полным именем каждого кастомного тега, например user.streak. Резолвер возвращает одно из следующих значений:
- Строка: пользователи видят её вместо тега. Она должна быть удобочитаемой, например «1 250», а не «1250.0». Adapty не форматирует и не переводит её.
null: пользователи видят начальное значение тега как запасной вариант.- Пустая строка: пользователи не видят ничего вместо тега.
Если вы создаёте AdaptyFlowView самостоятельно, передайте резолвер в его метод showFlow. В Jetpack Compose передайте его в AdaptyFlowScreen. Примеры каждого вызова смотрите в разделе Отображение флоу и пейволов.
Чтобы протестировать пользовательские теги, откройте флоу в своём приложении после добавления кода, который устанавливает их значения. Холст конструктора и предпросмотр на устройствах отображают только начальные значения: мобильное приложение Adapty не устанавливает значения пользовательских тегов.
Если ваше приложение уже задаёт значения кастомных тегов для старых пейволов Paywall Builder, ознакомьтесь с тем, чем кастомные теги во флоу отличаются от старых.
Что пользователи видят при отсутствии значения
Пользователи видят Начальное значение пользовательского тега как резервное в следующих случаях:
- Ваше приложение не передаёт никакого значения для тега.
- Пользователь не обновил приложение до версии, которая передаёт это значение.
- Имя в коде вашего приложения не совпадает с полным именем тега, включая регистр букв.
- Другой пользовательский тег в том же текстовом элементе не имеет значения. В этом случае каждый пользовательский тег в этом текстовом элементе показывает своё начальное значение.
Чтобы ничего не отображалось вместо тега, передайте пустую строку. Adapty считает пустую строку значением, поэтому резервный вариант не показывается.
Пример: показ ИМТ на основе ответов из онбординга
Флоу может собирать ответы пользователей, а кастомный тег — показывать значение из вашего приложения. Объедините эти возможности, чтобы показывать пользователям результат, который приложение вычисляет на основе их ответов: оценку, рекомендованный план или метрику здоровья:
- Флоу собирает ответы и передаёт их в ваше приложение.
- Приложение вычисляет результат.
- Приложение передаёт результат в следующий флоу в виде значения кастомного тега.
В этом примере онбординг-флоу собирает вес и рост пользователя. Когда пользователь закрывает онбординг-флоу после последнего экрана, приложение вычисляет индекс массы тела (ИМТ). Затем открывается пейвол-флоу, который показывает этот ИМТ.
Настройка флоу
-
Создайте два флоу: онбординг-флоу, собирающий вес и рост пользователя, и флоу-пейвол, показывающий его ИМТ.
-
Добавьте два поля Number в онбординг-флоу:
- Одно для веса в килограммах с Element ID
weight. - Одно для роста в сантиметрах с Element ID
height.
Для обоих полей установите Format в значение Integer. Поле отправляет значение как текст, точно так, как его ввёл пользователь, а пример кода не воспринимает «70.5» и «70,5» одинаково. Целые числа не содержат разделителя дробной части, поэтому код читает их одинаково в любой локали.
- Одно для веса в килограммах с Element ID
-
Чтобы убедиться, что приложение получает оба значения, завершите онбординг-флоу экраном без полей ввода. На этом экране добавьте кнопку с действием Close flow. Поля отправляют свои значения при потере фокуса или при переходе пользователя на другой экран. Действие Close flow не отправляет их. Пример кода открывает пейвол только в том случае, если пользователь добрался до последнего экрана.
-
В флоу-пейволе создайте кастомный тег с именем
bmi. В поле Initial value введите тире (—). Пользователь увидит тире, если приложение не передало значение ИМТ. -
Добавьте текстовый элемент со словами «Your BMI:» в флоу-пейвол. После этих слов вставьте кастомный тег
bmi. -
Добавьте онбординг-флоу в плейсмент, например
onboarding. Добавьте флоу-пейвол в плейсмент с IDbmi_paywall. Код из раздела Pass the BMI to the paywall получает пейвол по этому ID.
Передача BMI на пейвол
Собирайте данные о весе и росте из событий flow_user_input флоу онбординга, как описано в разделе Обработка данных из флоу. Чтобы определить, что пользователь достиг последнего экрана, отслеживайте событие flow_screen_showed с параметром is_last_screen, равным true, — подробнее в разделе Отслеживание просмотров экранов флоу. Когда пользователь закрывает флоу онбординга после этого экрана, вычислите BMI. Затем создайте представление флоу пейвола и передайте BMI в качестве значения кастомного тега bmi.
Передайте следующий листенер в представление флоу онбординга:
class OnboardingEventListener(
private val onBmiCalculated: (bmi: String) -> Unit,
) : AdaptyFlowDefaultEventListener() {
private val bodyAnswers = mutableMapOf<String, String>()
private var reachedLastScreen = false
override fun onAnalyticEvent(
name: String,
params: Map<String, Any?>,
context: Context,
) {
if (name == "flow_screen_showed" && params["is_last_screen"] == true) {
reachedLastScreen = true
return
}
if (name != "flow_user_input") return
val elementId = params["element_id"] as? String ?: return
val value = params["value"] as? String ?: return
bodyAnswers[elementId] = value
}
override fun onFlowClosed() {
// Reset `bodyAnswers` and `reachedLastScreen` on every close,
// so that the next run starts without old answers.
val answers = bodyAnswers.toMap()
val finished = reachedLastScreen
bodyAnswers.clear()
reachedLastScreen = false
// Number inputs send their values as strings.
if (!finished) return
val weight = answers["weight"]?.toDoubleOrNull() ?: return
val height = answers["height"]?.toDoubleOrNull()?.takeIf { it > 0 } ?: return
val heightInMeters = height / 100
val bmi = weight / (heightInMeters * heightInMeters)
onBmiCalculated(String.format(Locale.getDefault(), "%.1f", bmi))
}
}
Когда пользователь закрывает флоу онбординга после последнего экрана, слушатель вызывает onBmiCalculated с BMI. Передайте лямбду для onBmiCalculated, которая вызывает следующую функцию. Функция получает флоу пейвола, создаёт его представление и передаёт BMI для кастомного тега bmi:
fun showBmiPaywall(activity: Activity, bmi: String) {
Adapty.getFlow("bmi_paywall") { flowResult ->
when (flowResult) {
is AdaptyResult.Success -> {
AdaptyUI.getFlowConfiguration(flowResult.value) { configResult ->
when (configResult) {
is AdaptyResult.Success -> {
val flowView = AdaptyUI.getFlowView(
activity,
configResult.value,
products = null,
eventListener = AdaptyFlowDefaultEventListener(),
tagResolver = AdaptyUiTagResolver { tag ->
if (tag == "bmi") bmi else null
},
)
// add flowView to your view hierarchy
}
is AdaptyResult.Error -> {
// handle the error
}
}
}
}
is AdaptyResult.Error -> {
// handle the error
}
}
}
}
String.format с Locale.getDefault() использует десятичный разделитель локали пользователя: “22.7” для английского, “22,7” для немецкого.
Сохраните ИМТ в профиль пользователя
Чтобы показывать пользователям разные флоу в зависимости от их ИМТ, сохраните его как пользовательский атрибут профиля. В дашборде Adapty создайте пользовательский атрибут типа Number с ключом bmi. Затем показывайте каждый флоу аудитории, сформированной на основе этого атрибута.
Вызовите метод updateProfile внутри onFlowClosed, сразу после строки, вычисляющей bmi. Передайте значение типа Double, а не отформатированную строку — это позволит сегменту сравнивать ИМТ с пороговым значением:
val params = AdaptyProfileParameters.Builder()
.withCustomAttribute("bmi", bmi)
.build()
Adapty.updateProfile(params) { error ->
if (error != null) {
// handle the error
}
}