Passer au contenu

Configuration de l'interface utilisateur de la boîte de réception Pushwoosh sur Android

Pushwoosh Inbox UI fournit un écran de boîte de réception Android prêt à l’emploi (la boîte de réception de l’application avec l’icône en forme de cloche) qui s’appuie sur le backend de la boîte de réception Pushwoosh. Il affiche les messages sous l’un des cinq types de cartes, prend en charge les boutons d’appel à l’action (CTA) intégrés et permet la personnalisation du style via des attributs XML ou du code.

Prérequis

Anchor link to
  • Le SDK Android de base de Pushwoosh est déjà intégré et envoie des notifications push.
  • La prise en charge de Kotlin dans le module de votre application (apply plugin: 'kotlin-android').

Ajouter la bibliothèque

Anchor link to

Ajoutez le plugin Kotlin et les deux modules Pushwoosh au fichier build.gradle de votre application :

build.gradle
apply plugin: 'kotlin-android'
dependencies {
implementation 'com.pushwoosh:pushwoosh-inbox:6.+'
implementation 'com.pushwoosh:pushwoosh-inbox-ui:6.+'
}

Épinglez pushwoosh-inbox et pushwoosh-inbox-ui à la même version que votre dépendance com.pushwoosh:pushwoosh existante. Remplacez + par la version actuelle du SDK Android de Pushwoosh.

Si votre application utilise ProGuard pour la minification du code, conservez la classe du plugin de la boîte de réception :

proguard-rules.pro
-keep public class com.pushwoosh.inbox.PushwooshInboxPlugin {
*;
}

Afficher la boîte de réception

Anchor link to

Présentez la boîte de réception comme un écran autonome, ou intégrez-la comme un fragment dans votre propre mise en page.

En tant qu’activité :

startActivity(Intent(this, InboxActivity::class.java))

En tant que fragment :

supportFragmentManager.beginTransaction()
.replace(R.id.inboxContainer, PushwooshInboxUi.createInboxFragment())
.commitAllowingStateLoss()

Types de cartes

Anchor link to

L’interface utilisateur de la boîte de réception détermine un type de carte pour chaque message. Le résolveur lit displayType depuis l’objet data de la charge utile (payload) de la notification push, que le SDK fournit sous actionParams. Un displayType qui nomme un type de carte connu affichera toujours ce type, se rabattant sur classic uniquement si les champs requis pour ce type sont manquants. Cette résolution ne dépend pas du paramètre heuristique ci-dessous.

Lorsque displayType est absent, le message s’affiche comme une simple ligne, à moins que vous n’activiez l’heuristique image/texte :

PushwooshInboxStyle.richCardsHeuristicEnabled = true

Avec l’heuristique activée, une image sans titre s’affiche en tant que banner, une image avec un titre et un corps de texte s’affiche en tant que captioned, et tout le reste se rabat sur classic.

displayTypeApparenceChamp de payload requisSe dégrade en
bannerImage en pleine page, sans texteimage (icône du message ou data.attachment)classic en l’absence d’image
captionedImage en haut, titre + corps en dessousimage, title et content du messageclassic si l’image, le titre ou le corps est manquant
classicIcône + titre + corps— (titre, corps et icône attendus)—
carouselGalerie multi-images à balayertitle et content du message, data.carousel (1 à 5 diapositives)classic en l’absence de diapositives ou de titre/corps
videoAffiche avec un badge de lecture, lecteur plein écran au toucherdata.video (url + poster optionnel)classic en l’absence de descripteur

La carte Apple Wallet de l’InboxKit iOS n’a pas d’équivalent sur Android. Un message avec displayType: "wallet" s’affichera toujours en tant que classic sur Android.

Carte carrousel

Anchor link to

Les diapositives se trouvent dans data.carousel. Chaque diapositive nécessite une image. title (légende en superposition) et url (ouvert au toucher) sont optionnels. Une diapositive sans image est ignorée, et un maximum de 5 diapositives sont affichées.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"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]
}]
}
}

Carte vidéo

Anchor link to

Le descripteur se trouve dans data.video : url est requis, poster est une image d’aperçu optionnelle. Toucher l’affiche ouvre un lecteur en plein écran.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"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]
}]
}
}

Lire les données personnalisées d’un message

Anchor link to

Pour qu’une notification push apparaisse dans la boîte de réception, la requête createMessage de l’API Messages doit inclure inbox_image, inbox_date ou inbox_days. Sans l’un de ces champs, la notification push est livrée comme une notification ordinaire et n’atteint jamais le flux de la boîte de réception. Les données personnalisées de forme libre vont sous data, que le SDK expose en tant que actionParams sur InboxMessage :

PushwooshInboxUi.onMessageClickListener = OnInboxMessageClickListener { message ->
val params = message.actionParams?.let { JSONObject(it) }
val promoId = params?.optString("promo_id")
if (!promoId.isNullOrEmpty()) {
navigateToPromo(promoId)
}
}

Ajouter des boutons d’appel à l’action (CTA) intégrés

Anchor link to

Un message peut contenir des boutons d’appel à l’action intégrés dans data.buttons :

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"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]
}]
}
}

Chaque bouton nécessite un title. La résolution suit cette priorité :

  • action défini sur dismiss ou markRead (insensible à la casse) exécute cette action.
  • Sinon, une url non vide et analysable se résout en une action openURL.
  • Sinon, le toucher se résout en une action personnalisée, et chaque clé supplémentaire sur l’objet bouton est transmise à votre écouteur en tant que sa charge utile (payload).

Interceptez les touchers depuis PushwooshInboxUi.onButtonClickListener. Retournez true pour laisser le SDK effectuer l’action par défaut du bouton, false pour la supprimer :

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
}
}
}

Personnaliser le style

Anchor link to

Définissez les couleurs, les polices et les états vide/erreur depuis le code via 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 = false

Ou appliquez le même ensemble d’attributs en tant que thème, listés dans attrs.xml : inboxAccentColor, inboxTitleColor, inboxBackgroundColor, inboxDefaultIcon, et le reste des attributs de couleur et d’apparence. Les deux approches, ainsi qu’une application d’exemple complète, se trouvent dans le dépôt pushwoosh-inbox-ui-android-sdk InboxSample.

Badge des messages non lus

Anchor link to
PushwooshInbox.unreadMessagesCount { result ->
if (result.isSuccess) {
val count = result.data
} else {
Log.e("App", "Failed to get unread count", result.exception)
}
}