SDK Android (Kotlin)
LIKYLY montre à chaque utilisateur de votre application les produits qu’il a le plus de chances de vouloir : « Vous aimerez aussi » sur une fiche produit, « Recommandé pour vous » sur l’accueil. Il apprend de ce que font vos utilisateurs, simple consultation comprise.
Ce SDK tourne sur le téléphone de vos utilisateurs : il utilise donc la clé publique et couvre ce qu’elle permet. Il demande quoi afficher, signale ce que font les utilisateurs et ce que deviennent les recommandations, et garde un identifiant anonyme sur l’appareil. Votre catalogue, lui, est envoyé depuis votre serveur avec un SDK serveur et la clé secrète.
Toute app Android (minSdk 21+) et toute JVM · Kotlin, fonctions suspend · une seule dépendance : kotlinx-coroutines
Installation
// app/build.gradle.kts
dependencies {
implementation("com.likyly:likyly-android:1.0.0")
}Publié sur Maven Central. Votre app doit avoir la permission INTERNET (<uses-permission android:name="android.permission.INTERNET" />).
La clé publique, jamais la clé secrète
Tout ce qui est livré dans une application peut en être extrait. Utilisez la clé publique (pk_…, page Compte, « Clé publique ») : elle ne sait que demander des recommandations et enregistrer des événements. Le SDK refuse une clé secrète (sk_) ou développeur (lk_) dès sa création : l’erreur apparaît tout de suite, au lieu de partir dans une version publiée.
Démarrage rapide
1. Un client et une session pour toute l’application
class ShopApp : Application() {
lateinit var likyly: Likyly
lateinit var session: LikylySession
override fun onCreate() {
super.onCreate()
likyly = Likyly(BuildConfig.LIKYLY_PUBLIC_KEY) // la clé PUBLIQUE
session = LikylySession(FileAnonymousIdStore(filesDir)) // identifiant anonyme, gardé dans l'app
}
}2. Afficher un emplacement, et signaler ce qui a été vu et touché
viewModelScope.launch {
val result = try {
likyly.recommend(PlacementRequest(
placement = "pdp-related", // configuré une fois dans LIKYLY
context = PlacementContext(itemId = productId, userId = userId, sessionId = session.anonymousId),
limit = 4))
} catch (e: LikylyException) {
null // affichez votre propre contenu
}
_items.value = result?.items.orEmpty()
}
// Une carte devient visible (une fois par carte), puis est touchée :
likyly.events.impression(EventInput(itemId = item.itemId, sessionId = session.anonymousId,
recommendationId = result.recommendationId, placement = "pdp-related"))
likyly.events.click(EventInput(itemId = item.itemId, sessionId = session.anonymousId,
recommendationId = result.recommendationId, placement = "pdp-related"))Un emplacement (pdp-related, home-for-you…) se configure une fois dans LIKYLY, par votre assistant IA ou dans la console. Renvoyez le recommendationId sur l’impression et le clic : LIKYLY apprend quelles recommandations fonctionnent, et vous mesurez ce qu’elles rapportent.
3. Ce que font vos utilisateurs ailleurs dans l’application
likyly.events.view(EventInput(itemId = "SKU-456", userId = userId, sessionId = session.anonymousId))
likyly.events.addToCart(EventInput(itemId = "SKU-456", sessionId = session.anonymousId, quantity = 1))
// Un achat : eventId garantit qu'une nouvelle tentative ne le compte jamais deux fois
likyly.events.purchase(EventInput(itemId = "SKU-456", userId = userId, quantity = 1,
eventId = "purchase_${orderId}_SKU-456"))
likyly.events.track("favorite", EventInput(itemId = "SKU-456", userId = userId)) // vos propres typesLa consultation seule est utile : un utilisateur qui n’achète jamais apprend quand même à LIKYLY quels produits vont ensemble, et reçoit des recommandations. Renseignez un eventId sur les achats.
4. À la connexion
session.identify(likyly, userId) // à la connexion (le rappeler est sans effet)L’historique anonyme de l’appareil compte alors pour le compte de l’utilisateur.
Exemple complet : Un ViewModel complet.
Si LIKYLY ne répond pas
Les réponses des emplacements sont gardées en mémoire une heure : revenir sur un écran ne coûte rien. Après une erreur réseau, un délai dépassé, un 429 ou une erreur 5xx, les appels d’emplacement échouent aussitôt pendant 30 secondes (erreur « en pause ») : l’écran affiche son propre contenu au lieu d’attendre. Les deux se règlent ou se désactivent :
Likyly(key, LikylyOptions(cache = RecommendCacheOptions(ttlSeconds = 600, pauseSeconds = 15)))
Likyly(key, LikylyOptions(cache = null)) // ni cache, ni pause
likyly.clearRecommendationCache() // oublie les réponses en cacheNouvelles tentatives : 429, 502, 503, 504 et connexions coupées sont relancés avec un délai croissant (un Retry-After jusqu’à 60 s est respecté). Un événement sans eventId n’est jamais relancé après un échec ambigu : il n’est donc jamais enregistré deux fois.
Erreurs
Tout ce qui est levé est une LikylyException :
| Erreur | Quand |
|---|---|
ValidationException | Appel invalide, détecté avant l'envoi, ou 422 de l'API |
NetworkException | Aucune réponse HTTP : hors ligne, DNS, connexion coupée |
TimeoutException | La requête a expiré |
PausedException | LIKYLY a échoué il y a quelques secondes (retryInSeconds) : affichez votre contenu de repli |
AuthenticationException | 401 : clé absente, invalide ou révoquée |
PermissionDeniedException | 403 : par exemple une opération que la clé publique ne permet pas |
NotFoundException | 404 : par exemple un emplacement inconnu |
RateLimitException | 429 : voir retryAfterSeconds |
ApiException | Tout autre statut d'erreur (statusCode, requestId, body) |
Configuration
| Réglage | Option | Par défaut |
|---|---|---|
| URL de base | baseUrl | https://api.likyly.com |
| Catalogue | catalog | votre seul catalogue |
| Délai d'attente | timeoutMillis (par tentative) | 10 000 |
| Nouvelles tentatives | maxRetries | 2 |
| Suffixe User-Agent | userAgent | aucun |
| Cache des recommandations | cache | 1 heure ; pause de 30 s après un échec |
| Client HTTP | transport (LikylyTransport) | HttpURLConnection (OkHttp possible) |
Notes
- Bytecode Java 8 en Kotlin pur : fonctionne dans toute app Android et sur toute JVM, sans plugin Android Gradle. Aucune bibliothèque JSON ni HTTP n'est embarquée.
- L'annulation des coroutines n'est jamais enveloppée dans une
LikylyException: un écran quitté arrête proprement ses appels. LikylySessiongarde un identifiant aléatoire dans les fichiers privés de l'app : ce n'est pas l'identifiant publicitaire et il n'est jamais partagé avec d'autres apps.
Paquet : com.likyly:likyly-android sur Maven Central. Code source : github.com/Likyly/likyly-recsys/tree/main/sdk/android.