MAUI utilise le SDK .NET, qui cible netstandard2.0 et est le même paquet qu'utiliserait une application WPF, WinForms, Avalonia ou console ; voir mesurer une application pour ce qu'il remonte. Ce qui est propre à MAUI, c'est l'endroit où vous le démarrez, l'endroit où vous mettez sa file, et la façon dont les écrans reçoivent leurs noms.

Le code source, et une application de bureau de démonstration qui se mesure elle-même, sont sur skomi-sdk-dotnet.

Un client, pour la durée de vie de l'application

Enregistrez-le dans MauiProgram.cs pour que l'application en ait exactement un :

builder.Services.AddSingleton(_ => new SkomiClient(new SkomiOptions
{
    AppId = Guid.Parse("your-app-id"),          // depuis My Apps dans Skomi
    AppVersion = AppInfo.Current.VersionString,
    StoragePath = FileSystem.Current.AppDataDirectory,
}));

AppVersion vaut par défaut la version de l'assembly d'entrée, qui sur MAUI n'est pas la version que vous avez livrée à un store. AppInfo.Current.VersionString, si.

StoragePath décide de l'endroit où vit la file hors ligne. FileSystem.Current.AppDataDirectory est privé à l'application sur chaque cible MAUI et survit à une mise à jour, ce que le chemin de données d'application local par défaut ne fait pas de façon fiable sur mobile.

Libérez-le à l'extinction. Cela arrête le minuteur et fait une dernière tentative bornée de livraison ; ce qui ne part pas maintenant est sur le disque et partira au lancement suivant. Si vous l'avez enregistré en singleton, le conteneur d'injection le libère pour vous quand l'hôte s'éteint, mais une application MAUI est souvent tuée plutôt qu'éteinte, ce qui est la raison même de l'existence de la file.

Nommez vos écrans

skomi.Screen("checkout/review", new Dictionary<string, object?> { ["tier"] = "gold" });

Il n'y a pas de capture automatique des noms de pages : une classe de page est ce que votre code appelle un écran, pas ce que vous appelleriez ainsi dans un rapport. L'endroit naturel dans MAUI est un gestionnaire sur la navigation :

Shell.Current.Navigated += (_, e) =>
    skomi.Screen(e.Current.Location.OriginalString.Trim('/'));

Ce qui est un point de départ plutôt qu'une règle : les chaînes de route ne font des noms lisibles que si vos routes sont lisibles.

Erreurs

try
{
    await CheckoutAsync();
}
catch (Exception ex)
{
    skomi.CaptureError(ex, fatal: false, screenName: "checkout/review");
    ShowRetry();
}

Les défauts sont regroupés par type plutôt que par message, parce qu'un message porte des identifiants et des montants qui rendent chaque occurrence unique.

Ce n'est pas un rapporteur de plantages. Il enregistre les défauts que vous lui remettez et les exceptions managées qu'il peut voir ; un plantage natif sur Android ou iOS emporte le processus avant que quoi que ce soit puisse être écrit. Gardez le rapport du store, ou Crashlytics ou Sentry, pour ceux-là ; ce que Skomi ajoute, c'est un taux sans plantage à côté de vos chiffres de version, et les erreurs que vous avez choisi de rapporter.

Il n'y a pas non plus de téléversement de fichier de correspondance : une pile d'appels issue d'une compilation de production minifiée arrive telle qu'elle a été levée.

Il ne lève jamais d'exception dans votre code

Chaque méthode publique avale et rapporte via OnError, silencieux par défaut, ce qui est juste pour une application livrée et faux pendant que vous intégrez :

OnError = (ex, stage) => Debug.WriteLine($"Skomi {stage}: {ex}"),

Attendre le consentement

new SkomiOptions { AppId = id, Enabled = false }

Enabled = false n'enregistre rien et n'envoie rien : un client peut donc exister dès le démarrage et ne commencer à collecter qu'une fois que quelqu'un a donné son accord.

Vérifier que cela fonctionne

Lancez l'application, passez d'une page à l'autre, et regardez votre tableau de bord. Si rien n'arrive, réglez d'abord OnError : un identifiant d'application venu de la mauvaise application et un client jamais libéré sont les deux causes habituelles, et toutes deux sont silencieuses sans lui.