MAUI usa el SDK de .NET, que apunta a netstandard2.0 y es el mismo paquete que usaría una aplicación WPF, WinForms, Avalonia o de consola; véase medir una aplicación para lo que informa. Lo propio de MAUI es dónde lo arrancas, dónde pones su cola, y cómo reciben sus nombres las pantallas.

El código fuente, y una aplicación de escritorio de demostración que se mide a sí misma, están en skomi-sdk-dotnet.

Un cliente, para toda la vida de la aplicación

Regístralo en MauiProgram.cs para que la aplicación tenga exactamente uno:

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

AppVersion vale por defecto la versión del ensamblado de entrada, que en MAUI no es la versión que publicaste en una tienda. AppInfo.Current.VersionString sí lo es.

StoragePath decide dónde vive la cola sin conexión. FileSystem.Current.AppDataDirectory es privado de la aplicación en todos los destinos de MAUI y sobrevive a una actualización, cosa que la ruta de datos locales de aplicación por defecto no hace de forma fiable en móvil.

Libéralo al apagar. Eso detiene el temporizador y hace un último intento acotado de entrega; lo que no salga ahora está en el disco y sale en la siguiente ejecución. Si lo registraste como singleton, el contenedor de inyección lo libera por ti cuando el anfitrión se apaga, pero a una aplicación MAUI se la mata más a menudo de lo que se la apaga, que es la razón misma por la que existe la cola.

Nombra tus pantallas

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

No hay captura automática de nombres de página: una clase de página es lo que tu código llama una pantalla, no lo que tú llamarías así en un informe. El sitio natural en MAUI es un manejador en la navegación:

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

Que es un punto de partida y no una regla: las cadenas de ruta hacen nombres legibles solo si tus rutas son legibles.

Errores

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

Los fallos se agrupan por tipo y no por mensaje, porque un mensaje lleva identificadores e importes que hacen única cada ocurrencia.

Esto no es un informador de fallos. Registra los fallos que le entregas y las excepciones gestionadas que puede ver; un fallo nativo en Android o iOS se lleva el proceso por delante antes de que se pueda escribir nada. Guarda el informe de la propia tienda, o Crashlytics o Sentry, para esos; lo que añade Skomi es una tasa sin fallos junto a tus cifras de versión, y los errores que elegiste informar.

Tampoco hay subida de archivo de correspondencia, así que una pila de llamadas de una compilación de producción minificada llega tal como se levantó.

Nunca lanza una excepción dentro de tu código

Todos los métodos públicos se lo tragan e informan por OnError, que es silencioso por defecto, correcto para una aplicación publicada y equivocado mientras estás integrando:

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

Esperar el consentimiento

new SkomiOptions { AppId = id, Enabled = false }

Enabled = false no registra nada y no manda nada, así que un cliente puede existir desde el arranque y empezar a recoger solo una vez que alguien haya dado su acuerdo.

Comprobar que funciona

Ejecuta la aplicación, muévete entre dos páginas, y mira tu panel. Si no llega nada, pon primero OnError: un identificador de aplicación de la aplicación equivocada y un cliente que nunca se liberó son las dos causas habituales, y las dos son silenciosas sin él.