Свой UI и Custom JSON в Android
Используйте этот путь, когда приложение само рисует кампанию или рекомендации. SDK получает контент и отправляет content load tracking; видимость, клики и навигацию определяет приложение. Сначала выполните инициализацию.
getContentBySelector(...)
Для getContentBySelector(...) требуется корректно заполненный PageContext.
Пример:
lifecycleScope.launch {
val response = GravitySDK.instance.getContentBySelector(
selector = JSONObject.quote("homepage-banner-json"),
pageContext = PageContext(
type = ContextType.HOMEPAGE,
data = emptyList(),
location = "app://home",
)
)
if (response != null && response.data.isNotEmpty()) {
val campaign = response.data.first()
val variation = campaign.payload.firstOrNull()
val content = variation?.contents?.firstOrNull()
// Отрисуйте content в своем UI
}
}
Метод возвращает null при сетевой ошибке или ошибке разбора ответа; успешный ответ без подходящей кампании содержит пустой data. Успешная загрузка автоматически отправляет content load tracking для всех contents, но не показывает UI.
Для выбора по ID и группе доступны getContentByCampaignId(...) и getContentByGroupSelector(...): сигнатуры.
Все три метода используют общие Options/ContentSettings и отправляют content load tracking.
Формат selector в Android 1.0.4
В опубликованном AAR и его исходниках selector, group и campaign ID обрабатываются через Json.parseToJsonElement(...). Поэтому строковое значение нужно передавать как JSON-строку. Для произвольного selector используйте org.json.JSONObject.quote(...):
val sdkSelector = JSONObject.quote("homepage-recommendations")
val response = GravitySDK.instance.getContentBySelector(
selector = sdkSelector,
pageContext = pageContext,
)
Та же особенность действует для GravityInlineCompose, GravityInlineView, GravityInlineListView и строкового campaignId. В XML JSON-кавычки задаются как ". Это обход текущей реализации: имя selector в кабинете остаётся обычной строкой без добавленных кавычек. Не кодируйте уже подготовленное значение повторно.
SDK также сериализует ContentSettings под ключом option внутри data, в то время как iOS использует options. Если интеграция зависит от fields или skusOnly, проверьте фактический запрос и результат на вашем backend; документация не гарантирует, что backend применит эти настройки в Android 1.0.4.
Какие параметры нужны для получения контента
Для вызова getContentBySelector(...) обязательны:
selector;pageContext.type;pageContext.data;pageContext.location.
Опциональны:
lng;pageNumber;referrer;utm;attributes.
skusOnly и fields не передаются в метод напрямую. Они задаются один раз через setOptions(...) в ContentSettings и затем сериализуются в последующих запросах choose. Применение этих полей сервером в 1.0.4 проверьте с учётом ключа option, описанного выше.
Как устроен ответ ContentResponse
Упрощенно структура ответа выглядит так:
ContentResponse
-> data: List<Campaign>
-> payload: List<CampaignVariation>
-> contents: List<CampaignContent>
-> products?.slots: List<Slot>
Это важно для manual rendering и engagement:
campaignберите изresponse.data;contentберите изcampaign.payload[*].contents[*];slotберите изcontent.products?.slots[*].
decisionId присутствует в CampaignVariation, но публичные методы sendContentEngagement(...) и sendProductEngagement(...) не требуют передавать его отдельным параметром.
Custom JSON
Пользовательский JSON приходит в content.custom?.json как строка. Для кампании с JSON { "variant": "compact" } приложение само разбирает конфигурацию:
val campaign = response?.data?.firstOrNull()
val content = campaign?.payload?.firstOrNull()?.contents?.firstOrNull()
val config = content?.custom?.json?.let { raw ->
runCatching { JSONObject(raw) }.getOrNull()
}
val variant = config?.optString("variant", "control") ?: "control"
// Покажите UI для variant; неизвестное значение обработайте своим fallback.
Вариант A/B выбирает сервер. Сохраняйте campaign/content для engagement; impression отправляйте после фактического показа выбранного варианта, бизнес-события — в момент действия.
Отдельного параметра headless у native SDK нет. Методы выбора контента сами не показывают UI, но trackView(...) и triggerEvent(...) могут запустить in-app кампанию. Для собственного UI используйте selector/Custom JSON кампании. Presentation lock не отменяет HTTP-запросы и content load tracking.
Аналитика собственного UI
Загрузка не означает показ. Сохраните исходные campaign/content и при работе с товарами slot. Передавайте их в engagement после фактического взаимодействия:
Порог и дедупликацию реализует приложение. Встроенный Android detector использует 50% площади в течение секунды; полный пример дополнительно дедуплицирует показ каждого размещения.
Публичного ContentClickEngagement нет. sendContentEngagement/sendProductEngagement вызывают tracking URL, но не gravityEventCallback. Для бизнес-действий отправляйте TriggerEvent отдельно. Справочник engagement.