Configurando a UI da Caixa de Entrada do Pushwoosh para Android
A UI da Caixa de Entrada do Pushwoosh oferece uma tela de caixa de entrada pronta para Android (a Caixa de Entrada do Aplicativo com o “ícone de sino”) sobre o backend da caixa de entrada do Pushwoosh. Ela renderiza mensagens em um dos cinco tipos de cartão, suporta botões de CTA em linha e está aberta para personalização de estilo através de atributos XML ou código.
Pré-requisitos
Anchor link to- O SDK base do Pushwoosh para Android já integrado e enviando pushes.
- Suporte a Kotlin no módulo do seu aplicativo (
apply plugin: 'kotlin-android').
Adicionar a biblioteca
Anchor link toAdicione o plugin Kotlin e os dois módulos do Pushwoosh ao build.gradle do seu aplicativo:
apply plugin: 'kotlin-android'
dependencies { implementation 'com.pushwoosh:pushwoosh-inbox:6.+' implementation 'com.pushwoosh:pushwoosh-inbox-ui:6.+'}Fixe pushwoosh-inbox e pushwoosh-inbox-ui na mesma versão da sua dependência com.pushwoosh:pushwoosh existente. Substitua + pela versão atual do SDK do Pushwoosh para Android.
Se o seu aplicativo usa ProGuard para ofuscação de código, mantenha a classe do plugin da caixa de entrada:
-keep public class com.pushwoosh.inbox.PushwooshInboxPlugin { *;}Exibir a caixa de entrada
Anchor link toApresente a caixa de entrada como uma tela independente ou incorpore-a como um fragmento em seu próprio layout.
Como uma atividade (activity):
startActivity(Intent(this, InboxActivity::class.java))Como um fragmento (fragment):
supportFragmentManager.beginTransaction() .replace(R.id.inboxContainer, PushwooshInboxUi.createInboxFragment()) .commitAllowingStateLoss()Tipos de cartão
Anchor link toA UI da Caixa de Entrada resolve um tipo de cartão por mensagem. O resolvedor lê displayType do objeto data do payload do push, que o SDK entrega em actionParams. Um displayType que nomeia um tipo de cartão conhecido sempre renderiza esse tipo, recorrendo a classic apenas se os campos obrigatórios do tipo estiverem ausentes. Essa resolução não depende da configuração heurística abaixo.
Quando displayType está ausente, a mensagem é renderizada como uma linha simples, a menos que você opte pela heurística de imagem/texto:
PushwooshInboxStyle.richCardsHeuristicEnabled = trueCom a heurística ativada, uma imagem sem título renderiza banner, uma imagem com título e corpo renderiza captioned, e qualquer outra coisa recorre a classic.
displayType | Aparência | Campo obrigatório do payload | Degrada para |
|---|---|---|---|
banner | Imagem de sangria total, sem texto | imagem (ícone da mensagem ou data.attachment) | classic quando não há imagem |
captioned | Imagem no topo, título + corpo abaixo | imagem, title e content da mensagem | classic quando a imagem, título ou corpo estão ausentes |
classic | Ícone + título + corpo | — (título, corpo e ícone esperados) | — |
carousel | Galeria de múltiplas imagens deslizáveis | title e content da mensagem, data.carousel (1–5 slides) | classic quando não há slides ou não há título/corpo |
video | Pôster com selo de reprodução, reprodutor em tela cheia ao tocar | data.video (url + poster opcional) | classic quando não há descritor |
O cartão Apple Wallet do InboxKit para iOS não tem um equivalente para Android. Uma mensagem com displayType: "wallet" sempre é renderizada como classic no Android.
Cartão de carrossel
Anchor link toOs slides ficam em data.carousel. Cada slide precisa de uma image. title (sobreposição de legenda) e url (aberto ao tocar) são opcionais. Um slide sem imagem é descartado, e no máximo 5 slides são exibidos.
{ "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] }] }}Cartão de vídeo
Anchor link toO descritor fica em data.video: url é obrigatório, poster é uma imagem de visualização opcional. Tocar no pôster abre um reprodutor em tela cheia.
{ "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] }] }}Ler dados personalizados de uma mensagem
Anchor link toPara que um push apareça na caixa de entrada, a solicitação createMessage da API de Mensagens deve incluir inbox_image, inbox_date ou inbox_days. Sem um desses campos, o push é entregue como uma notificação regular e nunca chega ao feed da caixa de entrada. Dados personalizados de formato livre vão em data, que o SDK expõe como actionParams em InboxMessage:
PushwooshInboxUi.onMessageClickListener = OnInboxMessageClickListener { message -> val params = message.actionParams?.let { JSONObject(it) } val promoId = params?.optString("promo_id") if (!promoId.isNullOrEmpty()) { navigateToPromo(promoId) }}Adicionar botões de CTA em linha
Anchor link toUma mensagem pode conter botões de chamada para ação (call-to-action) em linha dentro de 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] }] }}Cada botão precisa de um title. A resolução segue esta prioridade:
actiondefinido comodismissoumarkRead(sem distinção entre maiúsculas e minúsculas) executa essa ação.- Caso contrário, uma
urlnão vazia e analisável resolve para uma açãoopenURL. - Caso contrário, o toque resolve para uma ação personalizada, e cada chave extra no objeto do botão é encaminhada para o seu ouvinte (listener) como seu payload.
Intercepte os toques de PushwooshInboxUi.onButtonClickListener. Retorne true para permitir que o SDK execute a ação padrão do botão, false para suprimi-la:
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 } }}Personalizar o estilo
Anchor link toDefina cores, fontes e estados de vazio/erro a partir do código através de PushwooshInboxStyle:
PushwooshInboxStyle.accentColor = ContextCompat.getColor(this, R.color.brand_accent)PushwooshInboxStyle.titleColor = ContextCompat.getColor(this, R.color.brand_title)PushwooshInboxStyle.listEmptyText = "You have no messages yet"PushwooshInboxStyle.showToolbar = falseOu aplique o mesmo conjunto de atributos como um tema, listado em attrs.xml: inboxAccentColor, inboxTitleColor, inboxBackgroundColor, inboxDefaultIcon e o restante dos atributos de cor e aparência. Ambas as abordagens, além de um aplicativo de exemplo completo, estão no repositório pushwoosh-inbox-ui-android-sdk InboxSample.
Selo de mensagens não lidas
Anchor link toPushwooshInbox.unreadMessagesCount { result -> if (result.isSuccess) { val count = result.data } else { Log.e("App", "Failed to get unread count", result.exception) }}