Функционал SDK
Предварительно вам необходимо настроить SDK для работы с вашим приложением. Подробная инструкция находится здесь
Работа со статусами подписки
Изменение статуса подписки
AltcraftSDK
└─ val pushSubscriptionFunctions: PublicPushSubscriptionFunctions
// Подписка (статус = SUBSCRIBED)
├─ fun pushSubscribe(
│ context: Context,
│ sync: Boolean = true,
│ profileFields: Map<String, Any?>? = null,
│ customFields: Map<String, Any?>? = null,
│ cats: List<DataClasses.CategoryData>? = null,
│ replace: Boolean? = null,
│ skipTriggers: Boolean? = null
│ ): Unit
// Приостановка (статус = SUSPENDED)
├─ fun pushSuspend(
│ context: Context,
│ sync: Boolean = true,
│ profileFields: Map<String, Any?>? = null,
│ customFields: Map<String, Any?>? = null,
│ cats: List<DataClasses.CategoryData>? = null,
│ replace: Boolean? = null,
│ skipTriggers: Boolean? = null
│ ): Unit
// Отписка (статус = UNSUBSCRIBED)
└─ fun pushUnSubscribe(
context: Context,
sync: Boolean = true,
profileFields: Map<String, Any?>? = null,
customFields: Map<String, Any?>? = null,
cats: List<DataClasses.CategoryData>? = null,
replace: Boolean? = null,
skipTriggers: Boolean? = null
): Unit
Функции изменения статуса подписки:
fun pushSubscribe()— выполняет подписку на push-уведомления;fun pushUnSubscribe()— отменяет подписку на push-уведомления;fun pushSuspend()— приостанавливает подписку на push-уведомления (уведомления не приходят, но при этом не создается событие отписки в профиле пользователя);fun unSuspendPushSubscription()— используется для созданияLogIn-,LogOut-переходов.
Функции этой группы имеют одинаковую сигнатуру, содержащую следующие параметры:
context: Context
Обязательный: Да
Описание: Android Context.
sync: Boolean
По умолчанию: true
Обязательный: Нет
Описание: Флаг, устанавливающий синхронность выполнения запроса.
Успешное выполнение запроса:
В случае успешного выполнения запроса данной группы функций будет создано событие с кодом 230, содержащее значение event.value, определяемое в зависимости от флага синхронизации:
Если sync == true
ResponseWithHttpCode
├─ httpCode: 200
└─ response
├─ error: 0
├─ errorText: ""
└─ profile
├─ id: "your id"
├─ status: "subscribed"
├─ isTest: false
└─ subscription
├─ subscriptionId: "your subscriptionId"
├─ hashId: "7f31a9c4"
├─ provider: "android-firebase"
├─ status: "subscribed"
├─ fields
│ ├─ _os_ver: {"raw":"14","ver":"[\"14.0\", \"0.0\", \"0.0\"]"}
│ ├─ _device_type: "mob"
│ ├─ _ad_track: true
│ ├─ _device_name: "Pixel"
│ ├─ _os_language: "en"
│ ├─ _os_tz: "+0100"
│ ├─ _os: "Android"
│ ├─ _device_model: "Pixel 7"
│ └─ _app_ver: "1.0.0"
└─ cats
└─ [ { name: "developer_news", title: "dev_news", steady: false, active: false } ]
При синхронном запро се в значении события event.value по ключу "response_with_http_code" доступны:
-
httpCode – транспортный код ответа;
-
Response – data class, содержащий:
-
error: Int?— внутренний код ошибки сервера (0, если ошибок нет), -
errorText: String?— текст ошибки (пустая строка, если ошибок нет), -
profile: ProfileData?— данные профиля, если запрос успешный:- информация о профиле (ProfileData)
- подписка (SubscriptionData)
- категории подписки (CategoryData)
- если запрос завершился с ошибкой, то вернется только
profile = null
-
Структуры данных
data class Response(
val error: Int?,
val errorText: String?,
val profile: ProfileData?
)
data class ProfileData(
val id: String?,
val status: String?,
val isTest: Boolean?,
val subscription: SubscriptionData?
)
data class SubscriptionData(
val subscriptionId: String?,
val hashId: String?,
val provider: String?,
val status: String?,
val fields: Map<String, Any?>?,
val cats: List<CategoryData>?
)
data class CategoryData(
val name: String?,
val title: String?,
val steady: Boolean?,
val active: Boolean?
)
Если sync == false
ResponseWithHttpCode
├─ httpCode: Int?
└─ response: Response?
├─ error: Int?
├─ errorText: String?
└─ profile: ProfileData? = null
При асинхронном запросе в значении события event.value по ключу "response_with_http_code" доступны:
-
httpCode – транспортный код ответа;
-
Response – data class, содержащий:
error: Int?— внутренний код ошибки сервера (0, если ошибок нет),errorText: String?— текст ошибки (пустая строка, если ошибок нет),profile: ProfileData?— данные профиля, для асинхронного запроса всегда равенnull.
Выполнение запроса с ошибкой:
Если запрос данной группы функций завершился ошибкой, будет создано событие со следующими кодами:
Операции без автоматического повтора попытки на стороне SDK:
- 430 – подписка на уведомления;
- 431 — приостановка подписки;
- 432 — отписка.
Операции с автоматическим повтором попытки на стороне SDK:
- 530 – подписка на уведомления;
- 531 — приостановка подписки;
- 532 — отписка.
Содержимое события:
- только
httpCode, если сервер Altcraft был недоступен; errorиerrorText, если сервер вернул ошибку.
Получение значений событий
AltcraftSDK.eventSDKFunctions.subscribe { event ->
val codes = setOf(
230, 231, 232,
430, 431, 432,
531, 532, 533
)
val code = event.eventCode ?: return@subscribe
if (code !in codes) return@subscribe
(event.eventValue?.get("response_with_http_code") as? DataClasses.ResponseWithHttpCode)?.let { responseWithHttp ->
val httpCode = responseWithHttp.httpCode
val response = responseWithHttp.response
val error = response?.error
val errorText = response?.errorText
val profile = response?.profile
val profileId = profile?.id
val profileStatus = profile?.status
val profileIsTest = profile?.isTest
val subscription = profile?.subscription
val subscriptionId = subscription?.subscriptionId
val hashId = subscription?.hashId
val provider = subscription?.provider
val subscriptionStatus = subscription?.status
val fields = subscription?.fields
val cats = subscription?.cats
val firstCat = cats?.firstOrNull()
val catName = firstCat?.name
val catTitle = firstCat?.title
val catSteady = firstCat?.steady
val catActive = firstCat?.active
}
}
profileFields:Map<String, Any?>?
По умолчанию: null
Обязательный: Нет
Описание: Словарь, содержащий поля профиля.
Параметр может принимать как системные поля (например, _fname — имя или _lname — фамилия), так и опциональные (заранее создаются вручную в интерфейсе платформы). Допустимые структуры (JSON-совместимые):
- Скалярные значения:
- String
- Boolean
- Int
- Long
- Float
- Double
null
- Объекты:
Map<String, *> - Списки:
List<*> - Массивы карт:
Array<Map<String, *>>
Если передано невалидное опциональное поле, запрос завершится с ошибкой:
SDK error: 430
http code: 400
error: 400
errorText: Platform profile processing error: with field "название_поля": Incorrect field
customFields:Map<String, Any?>?
По умолчанию: null
Обязательный: Нет
Описание: Словарь, содержащий поля подписки.
Параметр может принимать как системные поля (например, _device_model — модель устройства или _os — операционная система), так и опциональные (заранее создаются вручную в интерфейсе платформы). Допустимые типы значений (JSON-совместимые, только скаляры):
- String
- Boolean
- Int
- Long
- Float
- Double
null
Если передано невалидное опциональное поле, запрос завершится с ошибкой:
SDK error: 430
http code: 400
error: 400
errorText: Platform profile processing error: field "название_поля" is not valid: failed convert custom field
Большая часть системных полей подписки автоматически собирается SDK и добавляется к push-запросам. К таким системным полям относятся: "_os", "_os_tz", "_os_language", "_device_type", "_device_model", "_device_name", "_os_ver", "_ad_track", "_ad_id".
cats:listOf(CategoryData)
По умолчанию: null
Обязательный: Нет
Описание: Категории подписок.
Структура категории:
data class CategoryData(
val name: String?,
val title: String? = null,
val steady: Boolean? = null,
val active: Boolean?
)
При отправке push-запроса с указанием категорий используйте только поля name (название категории) и active (статус активности категории), другие поля не используется в обработке запроса. Поля title и steady заполняются при получении информации о подписке.
Пример запроса:
val cats = listOf(
DataClasses.CategoryData(name = "football", active = true),
DataClasses.CategoryData(name = "hockey", active = true)
)
Категории используемые в запросе должны быть предварительно созданы и добавлены к ресурсу в платформе Altcraft. Если в запросе будет использовано поле, которое не добавлено в ресурс — запрос вернется с ошибкой:
SDK error: 430
http code: 400
error: 400
errorText: Platform profile processing error: field "subscriptions.cats" is not valid: category not found in resource
replace:Boolean?
По умолчанию: null
Обязательный: Нет
Описание: При активации флага все подписки других профилей с тем же push-токеном в текущей базе данных переводятся в статус unsubscribed после успешного запроса.
skipTriggers:Boolean?
По умолчанию: null
Обязательный: Нет
Описание: При активации флага профиль, содержащий данную подписку, будет игнорироваться в триггерах рассылок и сценариев.
Примеры реализации запроса
Пример выполнения запроса подписки на push-уведомления
Минимальная рабочая настройка:
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(context)
Передача всех доступных параметров:
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(
context = this,
sync = true,
profileFields = mapOf("_fname" to "Andrey", "_lname" to "Pogodin"),
customFields = mapOf("developer" to true),
cats = listOf(DataClasses.CategoryData(name = "developer_news", active = true)),
replace = false,
skipTriggers = false
)
Для pushSubscribe, pushSuspend, pushUnSubscribe предусмотрен автоматический повтор запроса со стороны SDK если http-код ответа находится в диапазоне 500..599. Запрос не повторяется, если код ответа в этот диапазон не входит.
Функция unSuspendPushSubscription()
Функция fun unSuspendPushSubscription() предназначена для создания LogIn-, LogOut-переходов. Она работает следующим образом:
- проводит поиск подписок с тем же push-токеном, что и текущий, не относящихся к профилю, на который указывает текущий JWT-токен;
- меняет стату с для найденных подписок с
subscribedнаsuspended; - меняет статус в подписках профиля, на который указывает текущий JWT, с
suspendedнаsubscribed(если профиль на который указывает JWT существует и в нем содержатся подписки); - возвращает data class
ResponseWithHttpCode?, в которомresponse.profile— текущий профиль, на который указывает JWT (если профиля не существует, то вместоresponse.profileвернетсяnull).
Рекомендуемая реализация LogIn-, LogOut-переходов
LogIn-переход:
- Анонимный пользователь входит в приложение. Данному пользователю присвоен
JWT_1, указывающий на базу данных #1Anonymous; - Выполнена подписка на push-уведомления, профиль создан в базе данных #1Anonymous;
- Пользователь регистрируется, ему присваивается
JWT_2, указывающий на базу данных #2Registered; - Вызывается функция
unSuspendPushSubscription()— подписка анонимного пользователя в базе данных #1Anonymous приостанавливается; - Выполняется поиск профиля в базе данных #2Registered для восстановления подписки;
- Так как подписки с таким push-токеном в базе данных #2Registered не существует, функция
unSuspendPushSubscription()вернетnull; - После получения значения
nullможно выполнить запрос на подпискуpushSubscribe(), который создаст новый профиль в базе #2Registered.
LogOut-переход:
- Пользователь выполнил выход из профиля на стороне приложения (
LogOut); - Пользователю присваивается
JTW_1, указывающий на базу данных #1Anonymous; - Вызывается функция
unSuspendPushSubscription(), которая приостановит подписку базе данных в #2Registered и сменит статус подписки в базе #1Anonymous наsubscribed; - Запрос вернет
#1Anonymous != null— подписка уже существует, новая не требуется.
Пример реализации:
private suspend fun unSuspend(context: Context, logIn: Boolean) {
// Изменение JWT до запроса
setAuth(context, logIn)
AltcraftSDK.pushSubscriptionFunctions
.unSuspendPushSubscription(context)
?.let { result ->
if (result.httpCode == 200 && result.response?.profile?.subscription == null) {
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(
context = context
// Укажите необходимые параметры
)
}
}
}
fun logIn(context: Context) = CoroutineScope(Dispatchers.IO).launch { unSuspend(context, true) }
fun logOut(context: Context) = CoroutineScope(Dispatchers.IO).launch { unSuspend(context, false) }