MAUI usa l'SDK .NET, che punta a netstandard2.0 ed è lo stesso pacchetto che userebbe un'applicazione WPF, WinForms, Avalonia o da riga di comando; vedi misurare un'app per sapere che cosa riporta. Quello che è specifico di MAUI è dove lo avvii, dove metti la sua coda, e come le schermate prendono il nome.

Il codice sorgente, e un'app desktop di dimostrazione che misura se stessa, stanno su skomi-sdk-dotnet.

Un client, per tutta la vita dell'app

Registralo in MauiProgram.cs così che l'applicazione ne abbia esattamente uno:

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

AppVersion di serie prende la versione dell'assembly di ingresso, che su MAUI non è la versione che hai pubblicato su uno store. AppInfo.Current.VersionString lo è.

StoragePath decide dove vive la coda per quando non c'è rete. FileSystem.Current.AppDataDirectory è privato dell'app su ogni bersaglio MAUI e sopravvive a un aggiornamento, cosa che il percorso di serie dei dati locali dell'applicazione su mobile non fa in modo affidabile.

⚠ Dismettilo alla chiusura. Questo ferma il temporizzatore e fa un ultimo tentativo limitato di consegna; quello che non parte adesso è su disco e parte all'esecuzione successiva. Se l'hai registrato come singleton, il contenitore di iniezione lo dismette per te quando l'host si spegne, ma un'app MAUI spesso viene uccisa invece che spenta, che è il motivo per cui la coda esiste.

Dai un nome alle tue schermate

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

Non c'è nessuna cattura automatica dei nomi di pagina: la classe di una pagina è come il tuo codice chiama una schermata, non come la chiameresti in un report. Il posto naturale in MAUI è un solo gestore sulla navigazione:

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

È un punto di partenza, non una regola: le stringhe di rotta danno nomi leggibili solo se le tue rotte sono leggibili.

Errori

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

Gli errori sono raggruppati per tipo invece che per messaggio, perché un messaggio porta identificativi e importi che rendono unica ogni occorrenza.

⚠ Questo non è un sistema di segnalazione dei crash. Registra gli errori che gli consegni e le eccezioni gestite che riesce a vedere; un crash nativo su Android o su iOS si porta via il processo prima che si possa scrivere qualunque cosa. Tieni le segnalazioni di crash dello store stesso, o Crashlytics o Sentry, per quelli; quello che Skomi aggiunge è un tasso di sessioni senza crash accanto ai numeri delle tue versioni, e gli errori che hai scelto di segnalare.

Non c'è nemmeno il caricamento di un file di mappatura, quindi lo stack di una versione di rilascio minificata arriva com'è stato lanciato.

Non lancia mai eccezioni nel tuo codice

Ogni metodo pubblico inghiotte e segnala attraverso OnError, che di serie è silenzioso. È giusto per un'app pubblicata e sbagliato mentre stai integrando:

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

In attesa del consenso

new SkomiOptions { AppId = id, Enabled = false }

Con Enabled = false non si registra niente e non si manda niente, ed è così che si rispetta chi ha rifiutato. Non è un interruttore da accendere dopo: per aspettare il consenso, crea il client solo dopo che qualcuno ha acconsentito.

Controlla che funzioni

Fai girare l'app, passa fra due pagine, e guarda la tua dashboard. Se non arriva niente, imposta prima OnError: un identificativo di app dell'app sbagliata e un client mai dismesso sono le due cause solite, e senza di esso sono tutte e due silenziose.