O MAUI usa o SDK .NET, que tem como alvo o netstandard2.0 e é o mesmo pacote que uma aplicação WPF, WinForms, Avalonia ou de consola usaria; vê medir uma aplicação para saberes o que reporta. O que é específico do MAUI é onde o arrancas, onde pões a fila dele, e como os ecrãs ficam com nome.
O código-fonte, e uma aplicação de secretária de demonstração que se reporta a si mesma, estão em skomi-sdk-dotnet.
Um cliente, para toda a vida da aplicação
Regista-o no MauiProgram.cs para que a aplicação tenha exatamente um:
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,
}));
O AppVersion assume de origem a versão do assembly de entrada, que no MAUI não é a versão que entregaste a uma loja. O AppInfo.Current.VersionString é.
O StoragePath decide onde vive a fila para quando não há rede. O FileSystem.Current.AppDataDirectory é privado da aplicação em todos os alvos do MAUI e sobrevive a uma atualização, coisa que o caminho de origem dos dados locais da aplicação não faz de forma fiável em telemóveis.
⚠ Descarta-o ao desligar. Isso para o temporizador e faz uma última tentativa limitada de entrega; o que não for agora fica em disco e vai na execução seguinte. Se o registaste como singleton, o contentor de injeção descarta-o por ti quando o anfitrião desliga, mas uma aplicação MAUI é muitas vezes morta em vez de desligada, que é a razão de a fila existir de todo.
Dá nome aos teus ecrãs
skomi.Screen("checkout/review", new Dictionary<string, object?> { ["tier"] = "gold" });
Não há recolha automática de nomes de página: a classe de uma página é como o teu código chama a um ecrã, não como lhe chamarias num relatório. O lugar natural no MAUI é um único handler na navegação:
Shell.Current.Navigated += (_, e) =>
skomi.Screen(e.Current.Location.OriginalString.Trim('/'));
É um ponto de partida e não uma regra: as cadeias de rota só dão nomes legíveis se as tuas rotas forem legíveis.
Erros
try
{
await CheckoutAsync();
}
catch (Exception ex)
{
skomi.CaptureError(ex, fatal: false, screenName: "checkout/review");
ShowRetry();
}
Os erros são agrupados por tipo em vez de por mensagem, porque uma mensagem transporta identificadores e valores que tornam única cada ocorrência.
⚠ Isto não é um sistema de relatórios de falhas. Grava os erros que lhe entregas e as exceções geridas que consegue ver; uma falha nativa no Android ou no iOS leva o processo com ela antes de se conseguir escrever seja o que for. Mantém os relatórios de falhas da própria loja, ou o Crashlytics ou o Sentry, para essas; o que a Skomi acrescenta é uma taxa de sessões sem falhas ao lado dos números das tuas versões, e os erros que escolheste reportar.
Também não há envio de ficheiros de mapeamento, portanto uma pilha de uma versão minificada chega tal como foi lançada.
Nunca lança exceções para o teu código
Todos os métodos públicos engolem e reportam através do OnError, que é silencioso de origem. Isso é o certo para uma aplicação entregue e o errado enquanto estás a integrar:
OnError = (ex, stage) => Debug.WriteLine($"Skomi {stage}: {ex}"),
À espera do consentimento
new SkomiOptions { AppId = id, Enabled = false }
Com Enabled = false não se grava nada e não se envia nada, e é assim que se respeita quem recusou. Não é um interruptor para ligar mais tarde: para esperar pelo consentimento, cria o cliente só depois de alguém concordar.
Confirma que está a funcionar
Corre a aplicação, muda entre duas páginas, e olha para o teu painel. Se não chegar nada, define primeiro o OnError: um identificador de aplicação da aplicação errada e um cliente que nunca foi descartado são as duas causas habituais, e sem ele as duas são silenciosas.