Настройка Pushwoosh Inbox UI для Android
Pushwoosh Inbox UI предоставляет готовый экран входящих сообщений для Android (App Inbox, “иконка колокольчика”) поверх бэкенда Pushwoosh Inbox. Он отображает сообщения в виде одного из пяти типов карточек, поддерживает встроенные CTA-кнопки и позволяет настраивать стиль через XML-атрибуты или код.
Предварительные требования
Anchor link to- Базовый Pushwoosh Android SDK уже интегрирован и отправляет пуши.
- Поддержка Kotlin в вашем модуле приложения (
apply plugin: 'kotlin-android').
Добавление библиотеки
Anchor link toДобавьте плагин Kotlin и два модуля Pushwoosh в build.gradle вашего приложения:
apply plugin: 'kotlin-android'
dependencies { implementation 'com.pushwoosh:pushwoosh-inbox:6.+' implementation 'com.pushwoosh:pushwoosh-inbox-ui:6.+'}Закрепите версии pushwoosh-inbox и pushwoosh-inbox-ui на той же версии, что и ваша существующая зависимость com.pushwoosh:pushwoosh. Замените + на текущую версию Pushwoosh Android SDK.
Если ваше приложение использует ProGuard для сокращения кода, сохраните класс плагина входящих сообщений:
-keep public class com.pushwoosh.inbox.PushwooshInboxPlugin { *;}Отображение входящих
Anchor link toОтобразите входящие как отдельный экран или встройте его как фрагмент в ваш собственный макет.
Как activity:
startActivity(Intent(this, InboxActivity::class.java))Как fragment:
supportFragmentManager.beginTransaction() .replace(R.id.inboxContainer, PushwooshInboxUi.createInboxFragment()) .commitAllowingStateLoss()Типы карточек
Anchor link toInbox UI определяет тип карточки для каждого сообщения. Распознаватель читает displayType из объекта data полезной нагрузки пуша, который SDK доставляет под actionParams. displayType, именующий известный тип карточки, всегда отображает этот тип, возвращаясь к classic только в том случае, если обязательные поля типа отсутствуют. Это распознавание не зависит от настройки эвристики, описанной ниже.
Когда displayType отсутствует, сообщение отображается как простая строка, если вы не включите эвристику для изображений/текста:
PushwooshInboxStyle.richCardsHeuristicEnabled = trueПри включенной эвристике изображение без заголовка отображается как banner, изображение с заголовком и телом — как captioned, а все остальное — как classic.
displayType | Внешний вид | Обязательное поле в полезной нагрузке | Упрощается до |
|---|---|---|---|
banner | Изображение на всю ширину, без текста | изображение (иконка сообщения или data.attachment) | classic при отсутствии изображения |
captioned | Изображение сверху, заголовок + тело снизу | изображение, title и content сообщения | classic при отсутствии изображения, заголовка или тела |
classic | Иконка + заголовок + тело | — (ожидаются заголовок, тело и иконка) | — |
carousel | Галерея из нескольких изображений с возможностью прокрутки | title и content сообщения, data.carousel (1–5 слайдов) | classic при отсутствии слайдов или заголовка/тела |
video | Постер со значком воспроизведения, полноэкранный плеер по нажатию | data.video (url + опциональный poster) | classic при отсутствии дескриптора |
Карточка Apple Wallet из iOS InboxKit не имеет аналога на Android. Сообщение с displayType: "wallet" всегда отображается как classic на Android.
Карточка-карусель
Anchor link toСлайды находятся в data.carousel. Для каждого слайда требуется image. title (наложение подписи) и url (открывается по нажатию) являются необязательными. Слайд без изображения удаляется, и отображается не более 5 слайдов.
{ "request": { "application": "XXXXX-XXXXX", "auth": "API_TOKEN", "notifications": [{ "send_date": "now", "content": "Swipe through this week's drops", "inbox_days": 7, "data": { "displayType": "carousel", "carousel": [ { "image": "https://cdn.example.com/inbox/1.jpg", "title": "New in", "url": "myapp://product/1" }, { "image": "https://cdn.example.com/inbox/2.jpg", "title": "On sale", "url": "myapp://product/2" } ] }, "platforms": [3] }] }}Карточка-видео
Anchor link toДескриптор находится в data.video: url является обязательным, poster — необязательным изображением для предварительного просмотра. Нажатие на постер открывает полноэкранный плеер.
{ "request": { "application": "XXXXX-XXXXX", "auth": "API_TOKEN", "notifications": [{ "send_date": "now", "content": "Tap to play", "inbox_days": 7, "data": { "displayType": "video", "video": { "url": "https://cdn.example.com/inbox/clip.mp4", "poster": "https://cdn.example.com/inbox/poster.jpg" } }, "platforms": [3] }] }}Чтение пользовательских данных из сообщения
Anchor link toЧтобы пуш появился во входящих, запрос createMessage Messages API должен включать inbox_image, inbox_date или inbox_days. Без одного из этих полей пуш доставляется как обычное уведомление и никогда не попадает в ленту входящих. Произвольные пользовательские данные помещаются в data, которые SDK предоставляет как actionParams в InboxMessage:
PushwooshInboxUi.onMessageClickListener = OnInboxMessageClickListener { message -> val params = message.actionParams?.let { JSONObject(it) } val promoId = params?.optString("promo_id") if (!promoId.isNullOrEmpty()) { navigateToPromo(promoId) }}Добавление встроенных CTA-кнопок
Anchor link toСообщение может содержать встроенные кнопки призыва к действию (call-to-action) внутри data.buttons:
{ "request": { "application": "XXXXX-XXXXX", "auth": "API_TOKEN", "notifications": [{ "send_date": "now", "content": "Tap a button to claim or save", "inbox_image": "https://cdn.example.com/inbox/promo.png", "inbox_days": 7, "data": { "displayType": "captioned", "promo_id": "SUMMER2026", "buttons": [ { "title": "Claim", "url": "https://example.com/promo/SUMMER2026" }, { "title": "Read", "action": "markRead" }, { "title": "Save", "action": "custom", "tag": "save_promo" } ] }, "platforms": [3] }] }}Каждая кнопка требует title. Распознавание происходит в следующем порядке приоритета:
actionсо значениемdismissилиmarkRead(без учета регистра) выполняет это действие.- В противном случае, непустой и корректный
urlраспознается как действиеopenURL. - В противном случае, нажатие распознается как пользовательское действие, и каждый дополнительный ключ в объекте кнопки передается вашему слушателю в качестве его полезной нагрузки.
Перехватывайте нажатия с помощью PushwooshInboxUi.onButtonClickListener. Верните true, чтобы позволить SDK выполнить действие кнопки по умолчанию, или false, чтобы его подавить:
PushwooshInboxUi.onButtonClickListener = OnInboxButtonClickListener { message, button -> when (val action = button.action) { is InboxCardButton.Action.OpenUrl -> true InboxCardButton.Action.Dismiss, InboxCardButton.Action.MarkRead -> true is InboxCardButton.Action.Custom -> { when (action.payload.optString("tag")) { "save_promo" -> saveCurrentPromoLocally(message) } true } }}Настройка стиля
Anchor link toУстанавливайте цвета, шрифты и состояния “пусто”/“ошибка” из кода через PushwooshInboxStyle:
PushwooshInboxStyle.accentColor = ContextCompat.getColor(this, R.color.brand_accent)PushwooshInboxStyle.titleColor = ContextCompat.getColor(this, R.color.brand_title)PushwooshInboxStyle.listEmptyText = "У вас пока нет сообщений"PushwooshInboxStyle.showToolbar = falseИли примените тот же набор атрибутов в виде темы, перечисленных в attrs.xml: inboxAccentColor, inboxTitleColor, inboxBackgroundColor, inboxDefaultIcon и остальные атрибуты цвета и внешнего вида. Оба подхода, а также полное демонстрационное приложение, находятся в репозитории pushwoosh-inbox-ui-android-sdk InboxSample.
Значок непрочитанных сообщений
Anchor link toPushwooshInbox.unreadMessagesCount { result -> if (result.isSuccess) { val count = result.data } else { Log.e("App", "Failed to get unread count", result.exception) }}