Tutoriel du SDK Android Hodhod : un support natif dans votre app en 10 minutes
Ajoutez chat et tickets de support à votre app Kotlin et Compose avec le SDK Android Hodhod : dépendance, configuration, ouverture du chat, identification des utilisateurs par HMAC, thème, langue, compteur de non-lus et erreurs courantes.
Dans cet article
- SDK ou widget web dans une WebView ?
- Ce que le SDK inclut
- Prérequis
- Étape 1 : ajoutez la dépendance
- Étape 2 : configurez-le dans votre classe Application
- Étape 3 : ouvrez le chat
- Étape 4 : identifiez l'utilisateur
- Étape 5 : thème, langue et mode sombre
- Étape 6 : le compteur de non-lus
- Comportement des tickets et de l'enquête dans l'app
- Annonces et avertissements de la boîte
- R8 et ProGuard
- Dépannage
- Questions fréquentes
Vous avez une app Android, et vos clients y posent leurs questions. L'option la plus simple consiste à ouvrir le widget web dans une WebView. Mais si vous tenez à un rendu natif, au clavier Android, aux sélecteurs de pièces jointes et à la sensation d'une vraie app, le SDK Android Hodhod fait le même travail sans WebView. Il dialogue avec la même boîte de réception et la même API de widget que le widget web : les conversations et les tickets venus de l'app arrivent donc dans la même boîte de réception partagée de l'équipe.
Dans ce tutoriel, nous connectons pas à pas une app Kotlin au SDK : installation, configuration, ouverture du chat, identification de l'utilisateur, thème et langue, puis compteur de messages non lus. À la fin, vous verrez comment se comportent les tickets et l'enquête de satisfaction, et comment corriger les erreurs courantes.
La version actuelle du SDK est une bêta (
1.0.0-beta04). Les noms de classes et de paramètres ci-dessous viennent de cette version et peuvent changer avant la version stable.
SDK ou widget web dans une WebView ?
| Widget web dans une WebView | SDK Android | |
|---|---|---|
| Rendu | Une page web dans l'app | Interface Compose native, avec le design du widget Hodhod |
| RTL et police persane | Dépend de la page | RTL dès le départ, avec la police Vazirmatn incluse dans le SDK |
| Pièces jointes et appareil photo | Limités par la WebView | Sélecteurs de photos et de fichiers d'Android lui-même |
| Identification de l'utilisateur | Via JavaScript | Un seul appel Kotlin |
| Compteur de non-lus sur le bouton | Non | Oui |
| Thème clair et sombre | Dépend de la page | Suit le système, ou vous choisissez |
| Installation | Un extrait de code | Une dépendance Gradle |
Si votre app n'est qu'une page web dans une enveloppe Android, le widget web suffit. Si votre app est native et que le support fait partie de son expérience, le SDK est le meilleur choix.
Ce que le SDK inclut
- Modes de contact de la boîte : chat en direct, ticket, les deux, ou « ticket hors ligne ». Le réglage choisi dans le panneau pour le widget web s'applique aussi dans l'app.
- Tickets : un formulaire de ticket avec objet, description, catégorie et pièces jointes (selon la configuration de la boîte), une liste « mes tickets », et le fil de chaque ticket avec un badge de statut et les réponses.
- Enquête de satisfaction (CSAT) : trois styles d'affichage, emoji, étoiles et chiffres de 1 à 5, avec un champ de commentaire facultatif.
- Annonces et avertissements de la boîte (depuis
1.0.0-beta04) : les mêmes annonces que dans le widget web s'affichent en haut de l'écran de démarrage, sans code supplémentaire. - Formulaire de pré-chat, horaires de travail et jours fériés, bandeau d'avis de problème, fin de conversation et envoi de la transcription par e-mail, comme dans le widget web.
- Six langues : persan, anglais, arabe, allemand, espagnol et français. Les autres langues retombent sur l'anglais.
- Thème clair et sombre, couleur de marque de la boîte, et possibilité de forcer une couleur manuellement.
- Perte de connexion : quand le réseau ou le WebSocket tombe, un bandeau « pas de connexion » apparaît, le SDK se reconnecte tout seul, et un message dont l'envoi a échoué reste affiché avec un bouton « Réessayer ».
Prérequis
- Une boîte de réception « Site internet » dans le panneau Hodhod. Si vous n'en avez pas encore, suivez le guide d'installation du chat en direct jusqu'à la création de la boîte.
- Le
websiteTokende la boîte. C'est la même valeur que dans l'extrait de code du widget. minSdk24 ou supérieur, Kotlin et Java 17. Le SDK est compilé aveccompileSdk35 et son interface repose sur Jetpack Compose. Si votre app utilise encore des Views, appelezHodhod.openpour utiliser l'Activity prête à l'emploi ; les dépendances Compose sont ajoutées automatiquement.
Étape 1 : ajoutez la dépendance
Le SDK comporte deux modules : hodhod-core (sans interface : API, connexion en direct et logique) et hodhod-ui (l'interface Compose et une Activity prête à l'emploi). hodhod-ui embarque hodhod-core : pour l'interface prête à l'emploi, ce module suffit donc.
Le SDK est open source (MIT) sur github.com/HodHodChat/hodhod-android-sdk et s'installe via JitPack, qui le construit à partir du tag git 1.0.0-beta04 du dépôt. Ajoutez d'abord le dépôt JitPack à settings.gradle.kts :
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Ajoutez ensuite la dépendance :
// app/build.gradle.kts
dependencies {
implementation("com.github.HodHodChat.hodhod-android-sdk:hodhod-ui:1.0.0-beta04")
}
Les coordonnées sont com.github.HodHodChat.hodhod-android-sdk:hodhod-ui:1.0.0-beta04 (et ...:hodhod-core:1.0.0-beta04 si vous n'avez besoin que du core sans interface). Les noms de paquets Kotlin dans votre code restent chat.hodhod.sdk.
Étape 2 : configurez-le dans votre classe Application
Configurez le SDK une seule fois, dans Application.onCreate. Tant que Hodhod.start(), Hodhod.open() ou Hodhod.identify() n'a pas été appelé, le SDK n'envoie aucune requête réseau.
import android.app.Application
import chat.hodhod.sdk.Hodhod
import chat.hodhod.sdk.HodhodConfig
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Hodhod.configure(
this,
HodhodConfig(
baseUrl = "https://hodhod.chat", // votre serveur Hodhod, sans chemin supplémentaire
websiteToken = "YOUR_WEBSITE_TOKEN", // le jeton de la boîte « Site internet »
),
)
Hodhod.start() // facultatif : pour que le compteur de non-lus fonctionne avant l'ouverture du chat
}
}
Déclarez la classe dans AndroidManifest.xml avec android:name=".MyApp" sur la balise <application>. L'URL de base doit être en https:// ; la seule exception est un serveur local dans les builds de debug, traité dans la section « Dépannage ».
Étape 3 : ouvrez le chat
Il y a quatre façons de faire, de la plus simple à la plus personnalisée.
1. L'Activity prête à l'emploi. Une seule ligne depuis n'importe quelle Activity ou n'importe quel Fragment :
Hodhod.open(context)
Cela ouvre HodhodChatActivity : une page plein écran, avec un thème isolé du thème de votre app, qui gère elle-même le bouton retour. La même page s'ouvre aussi via le lien profond hodhod://chat.
2. L'intégrer à votre propre écran Compose. Si vous voulez le chat dans la navigation de votre app :
@Composable
fun SupportScreen(onBack: () -> Unit) {
HodhodChat(modifier = Modifier.fillMaxSize(), onClose = onBack)
}
Selon les réglages de la boîte, HodhodChat affiche l'écran d'accueil, le chat, les tickets et le formulaire de pré-chat, et appelle onClose quand l'utilisateur quitte le premier écran ou touche le bouton de fermeture. Si vous devez respecter la barre d'état et la barre de navigation, gérez les marges (insets) dans modifier ; HodhodChatActivity le fait avec windowInsetsPadding(WindowInsets.systemBars).
3. Un bouton flottant avec un badge de non-lus. HodhodBubble est un bouton rond qui affiche le nombre de messages non lus et appelle Hodhod.open au clic :
Box(Modifier.fillMaxSize()) {
// contenu de l'écran
HodhodBubble(Modifier.align(Alignment.BottomEnd).padding(16.dp))
}
Passez onClick pour un autre comportement. La couleur du bouton vient de la boîte, ou vous pouvez la changer avec le paramètre accent.
4. Votre propre bouton. N'importe quel bouton au design de votre app, comme « Support » dans l'écran de profil, appelle simplement Hodhod.open(context).
Étape 4 : identifiez l'utilisateur
Si l'utilisateur est connecté à votre app, présentez-le à Hodhod afin que les conversations et les tickets soient enregistrés à son nom et puissent aussi être retrouvés sur un autre appareil :
Hodhod.identify(
HodhodUser(
identifier = user.id, // un identifiant utilisateur stable dans votre système
identifierHash = hashFromBackend, // HMAC calculé sur votre backend
name = user.name,
email = user.email,
phone = user.phone,
customAttributes = mapOf("plan" to "pro"),
)
) { result ->
result.onFailure { Log.w("Support", "identify failed: ${it.message}") }
}
Sans identifier, l'utilisateur est un contact anonyme. Le résultat est livré sur le thread principal.
Pourquoi identifierHash, et pourquoi sur le backend ?
Si n'importe qui pouvait envoyer l'identifiant d'une autre personne, il pourrait lire ses conversations. Pour l'éviter, Hodhod conserve une clé HMAC secrète pour chaque boîte (dans les paramètres de la boîte, sous « Validation de l'identité de l'utilisateur ») et vérifie identifierHash ainsi : un HMAC SHA-256 de l'identifier avec cette clé, sous forme de chaîne hexadécimale.
La clé ne doit jamais se trouver dans l'app. Une fois l'utilisateur connecté, l'app obtient uniquement la valeur de identifierHash auprès de votre propre backend. Deux exemples :
// Node.js
import { createHmac } from 'node:crypto';
const identifierHash = createHmac('sha256', process.env.HODHOD_HMAC_KEY)
.update(String(user.id))
.digest('hex');
# Python
import hashlib, hmac, os
identifier_hash = hmac.new(
os.environ["HODHOD_HMAC_KEY"].encode(),
str(user.id).encode(),
hashlib.sha256,
).hexdigest()
En PHP, c'est la même chose : hash_hmac('sha256', (string) $user->id, $key). La chaîne identifier doit être strictement identique dans l'app et sur le backend.
Si vous activez « Forcer la validation de l'identité de l'utilisateur » dans les paramètres de la boîte, les requêtes sans identifierHash sont rejetées. Nous recommandons de l'activer pour que personne ne puisse accéder aux conversations d'une autre personne en devinant un identifiant.
Attributs personnalisés et déconnexion
Envoyez des attributs personnalisés (par exemple la version de l'app ou l'offre) avec HodhodUser ou séparément. Ils sont mis en file d'attente jusqu'à ce que la session existe :
Hodhod.setCustomAttributes(mapOf("app_version" to BuildConfig.VERSION_NAME))
Quand l'utilisateur se déconnecte de votre app :
Hodhod.logout()
Cela efface la session et les jetons stockés et ferme la connexion ; la prochaine utilisation crée un nouveau contact anonyme. Ainsi, la personne qui se connecte ensuite sur le même téléphone ne voit pas les conversations de l'utilisateur précédent.
Étape 5 : thème, langue et mode sombre
Tout se règle dans HodhodConfig :
HodhodConfig(
baseUrl = "https://hodhod.chat",
websiteToken = "YOUR_WEBSITE_TOKEN",
locale = "fa", // fa, en, ar, de, es ou fr
darkMode = DarkMode.AUTO, // AUTO (système), LIGHT ou DARK
accentColorOverride = 0xFF6A2BC4, // une couleur ARGB à la place de la couleur du widget de la boîte
)
- Langue :
localedans la configuration est prioritaire, puis la langue du compte sur le serveur, puis la langue de l'appareil. Une langue non prise en charge retombe sur l'anglais. Le sens d'écriture (RTL pour le persan et l'arabe) est réglé automatiquement. - Thème :
AUTOsuit le réglage du système. - Couleur : si vous ne passez pas
accentColorOverride, la couleur de widget définie pour la boîte dans le panneau est utilisée.
Étape 6 : le compteur de non-lus
Le nombre de messages non lus est un StateFlow<Int>. Il reste à zéro tant que Hodhod.start() ou Hodhod.open() n'a pas été appelé, c'est pourquoi nous avons ajouté start() à l'étape 2. Le compteur se met à jour en direct pendant que votre app tourne.
val unread by Hodhod.unreadCount.collectAsState()
BadgedBox(badge = { if (unread > 0) Badge { Text("$unread") } }) {
Icon(Icons.Outlined.SupportAgent, contentDescription = "Support")
}
Si vous utilisez HodhodBubble, il affiche ce compteur tout seul. L'état du chargement des paramètres se trouve dans Hodhod.state (Idle, Loading, Ready ou Failed).
Comportement des tickets et de l'enquête dans l'app
Ces comportements sont pilotés par les paramètres de la boîte dans le panneau et ne demandent aucun code :
- Mode de contact : en mode « chat », le client entre directement dans une conversation ; en mode « ticket », il voit le formulaire de ticket ; avec « les deux », il choisit. En mode « ticket hors ligne », le chat en direct est affiché pendant que l'équipe travaille et le formulaire de ticket s'ouvre en dehors des horaires de travail. Ce mode dépend des horaires de travail définis sur la boîte.
- Tickets : après l'envoi, le numéro du ticket est affiché, et depuis « Mes tickets » le client voit le statut (ouvert, en cours, en attente de votre réponse, résolu, fermé) et répond dans le même fil. Pour la différence entre tickets et chat, lisez l'article sur le ticketing et le chat en direct (ticketing vs live chat).
- Enquête : une fois la conversation terminée, si l'enquête de la boîte est activée, une carte de notation de 1 à 5 apparaît dans le style défini pour la boîte (emoji, étoiles ou chiffres). Si le résultat vous importe, voir qu'est-ce que le CSAT.
- Après la fin d'une conversation : le client revient à l'écran de départ et, selon le mode de contact, peut ouvrir un nouveau chat ou un nouveau ticket.
- Formulaire de pré-chat : s'il est activé pour la boîte, il s'affiche avant la première conversation. Voir le formulaire de pré-chat.
Flux de chatbot
Les flux de chatbot s'exécutent nativement dans le SDK Android, sans code de votre côté. Si la boîte a un flux actif, l'app l'affiche sur l'écran de démarrage : les 17 types de nœuds, variables et conditions, validation des saisies et notes. Le visiteur peut être transféré à un agent en direct ou sous forme de ticket, et les mêmes analyses de flux que le widget web sont enregistrées. Si l'option require_flow du flux est activée, la carte directe « Démarrer la conversation » reste masquée tant que le flux est disponible (elle revient si le flux ne peut pas être chargé). Le moteur a été comparé au moteur web avec 40 scénarios de parité (mêmes étapes, variables et événements), et les écrans ont été vérifiés sur émulateur en persan (RTL) et en anglais. Le flux ne s'édite que dans le tableau de bord.
Annonces et avertissements de la boîte
Depuis 1.0.0-beta04, le SDK affiche tout seul, sans code, les annonces que vous avez configurées pour la boîte dans le panneau, en haut de l'écran de démarrage de l'app. Les réglages sont les mêmes que pour le widget web (réglages de la boîte, section « Widget announcements ») ; pour savoir comment les créer et les rédiger, lisez annonces et avertissements dans le widget de support.
- Où elles s'affichent : en haut de l'accueil, de l'écran des tickets quand il fait office d'accueil, et du formulaire de pré-chat, au-dessus du moteur de flux et des cartes de démarrage. Le bandeau d'avis de problème vient après elles.
- Jusqu'à deux, à deux niveaux : une « annonce » jaune avec une icône d'information et un « avertissement » rouge avec une icône d'alerte, en thème clair et sombre et de droite à gauche.
- Texte et liens : des passages en gras et des liens sur une partie du texte. Seuls
http,https,mailtoettels'ouvrent, dans l'application correspondante (navigateur, téléphone, e-mail) et jamais dans une WebView. - Image : une seule image en
https, avec une description pour TalkBack et un lien facultatif ; elle est masquée si elle ne se charge pas. - Fermeture : une annonce fermable a un bouton de fermeture et le choix de l'utilisateur est mémorisé sur cet appareil. Si vous modifiez dans le panneau le texte, le niveau ou l'option « Visitors can close it », l'annonce s'affiche de nouveau.
- Programmation : le serveur n'envoie que les annonces activées et situées dans leur plage horaire ; le SDK n'a rien à faire pour cela.
- Anciens serveurs : si le serveur n'a pas cette fonctionnalité, aucune annonce n'est affichée et le reste du SDK fonctionne normalement.
Si vous avez construit votre propre interface, les annonces qui n'ont pas été fermées se trouvent dans un StateFlow. HodhodChat et Hodhod.open s'en chargent eux-mêmes et n'ont pas besoin du code ci-dessous :
val items by Hodhod.repository.announcements.collectAsState() // not closed yet, refreshed with the widget config
// e.g. from a close button of your own UI; ignored for announcements visitors cannot close
items.firstOrNull()?.let { Hodhod.repository.dismissAnnouncement(it.id) }
R8 et ProGuard
Les règles nécessaires sont incluses dans les bibliothèques (consumer-rules.pro) : vous n'avez rien à ajouter pour un build de release. Elles conservent les sérialiseurs des modèles du SDK et HodhodChatActivity, que Hodhod.open recherche par son nom. Si vous avez déjà une règle pour l'Activity, la répéter ne pose pas de problème. Si vous activez shrinkResources, les chaînes et les polices du SDK sont conservées par le fichier keep fourni avec lui.
Dépannage
L'écran de chat affiche une erreur ou ne se charge pas. Lisez Hodhod.state ; dans l'état Failed, il contient un code :
not_found: lewebsiteTokenou lebaseUrlest incorrect.network: le téléphone n'arrive pas à joindre le serveur.suspended: le compte Hodhod est suspendu.server: erreur du serveur ; réessayez dans un instant.cleartext: vous avez passé une adresse enhttp://.
Un serveur local (10.0.2.2) n'arrive pas à se connecter. Dans l'émulateur, le localhost de votre machine est 10.0.2.2. Comme l'adresse est en http://, il faut deux choses, uniquement pour les builds de debug : passer allowCleartext = true dans HodhodConfig, et, dans un network_security_config de debug, autoriser le trafic en clair pour 10.0.2.2 uniquement (l'app d'exemple du SDK en fournit un exemple). N'utilisez ni l'un ni l'autre dans les builds de release.
Les messages n'arrivent pas en direct et le bandeau « pas de connexion » s'affiche. Les mises à jour en direct passent par un WebSocket sur le chemin /cable. Un proxy d'entreprise, un pare-feu ou un CDN peut bloquer la mise à niveau (upgrade) vers WebSocket. Le SDK se reconnecte avec un délai croissant ; essayez le même chemin depuis un autre réseau.
La langue est incorrecte. Passez locale explicitement dans HodhodConfig. Sans lui, la langue du compte Hodhod (sur le serveur) est utilisée, puis la langue de l'appareil. Des codes comme fa-IR sont acceptés et ramenés à fa.
identify échoue. Le plus souvent, identifierHash est incorrect. Vérifiez que vous avez utilisé la clé HMAC de la boîte (et non le websiteToken), que l'identifier est identique dans l'app et sur le backend, et que le hachage est écrit en hexadécimal.
Questions fréquentes
En quoi le SDK Android diffère-t-il du widget web ?
Le widget web est une page web qui s'installe sur votre site avec un extrait de code. Le SDK est une interface Android native construite avec Jetpack Compose, qui se connecte à la même boîte de réception et à la même API. Dans les deux cas, les conversations arrivent dans une boîte de réception partagée unique.
Mon app doit-elle être écrite en Compose ?
Non. Hodhod.open(context) fonctionne depuis n'importe quelle Activity. Seuls l'intégration de HodhodChat et le bouton HodhodBubble exigent Compose.
Quelles versions d'Android sont prises en charge ?
minSdk est 24 (Android 7.0 et supérieur).
Ai-je besoin d'une boîte de réception séparée ?
Non. Le SDK utilise la même boîte « Site internet », avec le même websiteToken. Si vous voulez garder les conversations de l'app à part, créez une autre boîte « Site internet » pour l'app.
Les flux de chatbot fonctionnent-ils dans l'app ?
Oui. Si la boîte a un flux de chatbot actif, le SDK l'exécute nativement sur l'écran de démarrage, avec transfert à un agent en direct ou sous forme de ticket. Aucun code n'est nécessaire en plus de la configuration normale.
Comment distinguer les contacts des utilisateurs de l'app ?
Par l'identifier que vous fournissez. Pour empêcher l'usurpation, calculez identifierHash sur votre backend avec la clé HMAC de la boîte, et activez la validation d'identité obligatoire.
Les annonces de la boîte s'affichent-elles aussi dans l'app ?
Oui, depuis 1.0.0-beta04. Le SDK affiche les annonces et avertissements configurés pour la boîte en haut de l'écran de démarrage ; aucun code n'est nécessaire et la fermeture d'une annonce est mémorisée sur cet appareil. La façon de les créer est expliquée dans annonces et avertissements dans le widget de support.


