← Tous les SDK

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 types

La 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 cache

Nouvelles 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 :

ErreurQuand
ValidationExceptionAppel invalide, détecté avant l'envoi, ou 422 de l'API
NetworkExceptionAucune réponse HTTP : hors ligne, DNS, connexion coupée
TimeoutExceptionLa requête a expiré
PausedExceptionLIKYLY a échoué il y a quelques secondes (retryInSeconds) : affichez votre contenu de repli
AuthenticationException401 : clé absente, invalide ou révoquée
PermissionDeniedException403 : par exemple une opération que la clé publique ne permet pas
NotFoundException404 : par exemple un emplacement inconnu
RateLimitException429 : voir retryAfterSeconds
ApiExceptionTout autre statut d'erreur (statusCode, requestId, body)

Configuration

RéglageOptionPar défaut
URL de basebaseUrlhttps://api.likyly.com
Cataloguecatalogvotre seul catalogue
Délai d'attentetimeoutMillis (par tentative)10 000
Nouvelles tentativesmaxRetries2
Suffixe User-AgentuserAgentaucun
Cache des recommandationscache1 heure ; pause de 30 s après un échec
Client HTTPtransport (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.
  • LikylySession garde 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.