16. Jan 2023
Lesedauer 18 Min.
App Center für .NET MAUI
Monitoring
Überwachung und Diagnose für .NET-MAUI-Apps.

Wer an Monitoring denkt, denkt an Sentry. Aber da gibt es auch das Visual Studio App Center von Microsoft. Voll integriert in Azure, kostenlos nutzbar und so einfach zu verwenden, dass der Fokus auf der App-Entwicklung bleibt.Als Microsoft sich immer mehr der Kritik ausgesetzt sah, die Menüstruktur von Word sei überfrachtet, bestand Handlungsbedarf. Microsoft tat das einzig Richtige: Der Umgang der Nutzer mit Word wurde gemessen und die Metriken entsprechend ausgewertet. Das Ergebnis war dann die Einführung der Multifunktionsleisten (Ribbons) mit Office 2007.Die Geschichte zeigt, wie wichtig es ist, nach der Veröffentlichung einer Applikation immer einen guten Blick darauf zu haben, wie sie performt, welche Funktionen überhaupt (und wie) genutzt werden und an welchen Stellen es Probleme gibt.An dieser Stelle kommt das Monitoring ins Spiel. Doch leider nehmen aufgrund von Fragen zur Bedienung einer App, die für irgendeinen Betrag zwischen 0,79 und 4,99 Euro angeboten wird oder gar kostenlos war, nur die wenigsten Benutzer direkt und persönlich Kontakt auf. Ist Ihre App nicht intuitiv bedienbar? Im typischen Fall erhalten Sie eine negative 1-Stern-Bewertung, und dann wird eine alternative App eines Konkurrenten heruntergeladen.Gut wäre es also, wenn Sie die Möglichkeiten hätten, immer genauestens zu verstehen, wie die Nutzer Ihre Apps bedienen, und Sie praktisch in Echtzeit darüber in Kenntnis gesetzt werden, sobald dabei Probleme auftreten.
Historie und Status quo
Wie bei vielen anderen Microsoft-Produkten auch gibt es hinter App Center eine Geschichte. Die beginnt bei einem Open-Source-Tool, das Möglichkeiten anbot, Beta-Apps auf iOS-Geräten zu installieren. Apple spricht von einer Ad-hoc-Distribution, woraus die Entwickler des Open-Source-Tools den Namen Hockey ableiteten und später noch App hinten dranhängten.Die HockeyApp bot nach und nach immer mehr Features an. Darunter alles, was das Continuous-Deployment-Herz begehrt – inklusive Testing, Distribution, Crash Reporting und Metriken. Sie war so erfolgreich, dass Microsoft das Tool 2014 übernahm und in die Visual Studio Online Application Insights Services überführte. Aus Visual Studio Online wurde nach und nach Azure DevOps und aus der HockeyApp fünf Jahre später, im Jahr 2019, endgültig das Visual Studio App Center (Bild 1). Nach dieser kleinen Geschichtsstunde sollen die Spiele dann auch endlich beginnen!
Visual Studio App Center:Die Mission Control für Apps(Bild 1)
Bild: https://appcenter.ms/
Level 1: Anlegen einer App in App Center
Microsoft bewirbt App Center mit den Worten „[…] for every platform“. Das stimmt grundsätzlich zwar, allerdings ist die Auswahl im Dialog Add new app auf folgende Plattformen beschränkt: Objective-C/Swift, React Native, Xamarin und Unity. Im Wissen, dass .NET MAUI auf der Evolutionsleiter eine Sprosse höher steht als Xamarin – und auch ein (sehr) direkter Nachfahre ist –, hat sich gezeigt, dass App Center auch kompatibel zu .NET MAUI ist.Zumindest war es das während der Preview-Phase von .NET MAUI. Nachdem das Framework den Status mehrerer Release Candidates hinter sich gelassen hatte, gab es abschließend noch ein großes Refactoring, und damit war die Kompatibilität der App-Center-Pakete zu .NET MAUI zunächst einmal für viele Monate passé.Ende September 2022 aber erwachte das Produkt aus seinem Dornröschenschlaf, und nachdem immer mehr ehemalige Xamarin-Entwickler dazu übergingen, Sentry als Monitoring-Produkt in ihren neuen .NET-MAUI-Applikationen einzusetzen, veröffentlichte Microsoft endlich ein Update für die App-Center-Bibliotheken mit dem Hinweis, dass sie nun auch wieder mit .NET MAUI genutzt werden können – .NET-6-Bindings sei Dank.Und das geht so: Nach der erfolgreichen Anmeldung beim Visual Studio App Center über [1] gelangen Sie über die Schaltfläche Add new app in einen Dialog, in dem Sie den Namen Ihrer App, ein Icon und den Release Type auswählen. Da die unterschiedlichen Plattformbetreiber jeweils eigene Distributionskanäle haben, wählen Sie zunächst das Betriebssystem aus und abschließend die Plattform. Es ist wichtig zu verstehen, dass es somit in Bezug auf eine .NET-MAUI-App für jedes System eine eigene Konfiguration in App Center gibt (iOS, Android et cetera). Da es (noch) keine Möglichkeit gibt, dediziert .NET MAUI als Plattform auszuwählen, wählen Sie Xamarin als Ziel aus, siehe Bild 2. Im Anschluss landen Sie in der Übersicht und einer freundlichen Getting Started-Seite, die für Xamarin und Xamarin.Forms die ersten Schritte erläutert: NuGet-Pakete hinzufügen, SDK initialisieren, App Secrets integrieren, und dann kann es auch schon losgehen.
Xamarinwird ausgewählt, um App Center für .NET MAUI nutzen zu können(Bild 2)
Autor
War es das schon?
Spoiler: Nein, das war es nicht. Aber hier zeichnet sich ein gelungener Start ab. Hier der wichtigste Hinweis gleich zu Beginn: Bei der Suche nach „App Center“ im NuGet-Paketmanager müssen Sie derzeit noch das Häkchen bei Include prereleases setzen. Denn die aktuelle stabile Version von App Center steht noch auf Version 4.5.3. Erst die kommende Version 5.0 enthält zu .NET MAUI kompatible Bindings und befindet sich seit dem 29. September in der Preview 1. Es sind entsprechend die Pakete Microsoft.AppCenter.Analytics und Microsoft.AppCenter.Crashes zu installieren (Bild 3).
Diese NuGet-Paketesind zu installieren(Bild 3)
Autor
Am dichtesten dran an .NET MAUI ist Xamarin.Forms. Insofern könnten die Instruktionen an der Stelle auf der Übersichtsseite für Ihren Einstieg interessant sein. Allerdings offenbart sich auch direkt die erste Frage: Wo genau soll nun das SDK „gestartet“ werden? So gibt es in .NET MAUI beispielsweise kein geteiltes oder portables Projekt, da es hier lediglich ein Projekt gibt (to rule them all).
Level 2: Der Schnelleinstieg
Bevor es in wenigen Momenten losgeht, vorab ein dringender Hinweis: Praktisch alles, was es so in der Welt der Softwareentwicklung gibt, existiert auf verschiedenen Komplexitätsstufen. Das reicht von „Einfach, möglicherweise aber etwas ineffizient und bestimmt auch mit der einen oder anderen Sicherheitslücke“ bis hin zu „Benötigt ein Studium, viel Zeit, ist dafür maximal Performance-orientiert und folgt dem Konzept: Security-First“. So ist es auch mit dem App Center. Denn was Microsoft mitten im Fließtext mit nur einem Einschub andeutet, kann gut und gerne ein paar Tage Einarbeitungszeit mit sich bringen:„Copy the app secret below, store it in your secure place such as Azure Key Vault, and integrate it into your application using your CI tools.“Je nach vorhandener Erfahrung deuten sich hier diverse Herausforderungen an, lesen Sie dazu auch den Kasten Wie geheim sollte das App Secret sein?. Doch bevor wir auch diese Hürden überwinden, probieren Sie Visual Studio App Center doch erst einmal aus!Wie geheim sollte das App Secret sein?
Beim App Secret handelt es sich um eine GUID, die einzigartig ist und die entsprechende App in Visual Studio App Center eindeutig identifiziert. Kenntnis über diese ID ermöglicht es Dritten, beispielsweise Daten an die jeweiligen Endpunkte zu senden und somit Analysedaten und Metriken mit Nonsense zu fluten. Ob dieses Risiko als ein solches eingestuft wird oder nicht, bleibt jedem selbst überlassen. Die grundsätzliche Empfehlung lautet dennoch: Genau wie andere sicherheitsrelevante Schlüssel auch haben die App Secrets nichts im Quellcode zu suchen, insbesondere wenn es sich dabei um ein Open-Source-Produkt handelt.
In der Annahme, dass Ihnen zum Testen eine Standard-MAUI-App vorliegt – entweder über das Default-Template oder aber (sehr zu empfehlen) über den MAUI App Accelerator generiert [2] –, lautet die einfachste Empfehlung, das App Center direkt in CreateMauiApp zu starten, siehe Listing 1.
Listing 1: Starten des App Center SDK in einer .NET-MAUI-App
<span class="hljs-title">public</span> static <span class="hljs-type">MauiApp</span> <span class="hljs-type">CreateMauiApp</span>() <br/>{ <br/> var builder = <span class="hljs-type">MauiApp</span>.<span class="hljs-type">CreateBuilder</span>(); <br/> builder <br/> .<span class="hljs-type">UseMauiApp</span>&lt;<span class="hljs-type">App</span>&gt;() <br/> .<span class="hljs-type">ConfigureFonts</span>(fonts =&gt; <br/> { <br/> fonts.<span class="hljs-type">AddFont</span>(<br/> <span class="hljs-string">"OpenSans-Regular.ttf"</span>, <span class="hljs-string">"OpenSansRegular"</span>); <br/> fonts.<span class="hljs-type">AddFont</span>(<span class="hljs-string">"OpenSans-Semibold.ttf"</span>,<br/> <span class="hljs-string">"OpenSansSemibold"</span>); <br/> }); <br/><br/> <span class="hljs-type">AppCenter</span>.<span class="hljs-type">Start</span>(<span class="hljs-string">"ios=xxxxxxxx-xxxx-xxxx-xxxx-</span><br/><span class="hljs-string"> xxxxxxxxxxxx;"</span>, <br/> typeof(<span class="hljs-type">Analytics</span>), typeof(<span class="hljs-type">Crashes</span>)); <br/><br/> builder.<span class="hljs-type">Services</span>.<span class="hljs-type">AddSingleton</span>&lt;<span class="hljs-type">MainViewModel</span>&gt;(); <br/> builder.<span class="hljs-type">Services</span>.<span class="hljs-type">AddSingleton</span>&lt;<span class="hljs-type">MainPage</span>&gt;(); <br/><br/> return builder.<span class="hljs-type">Build</span>(); <br/>}
Hier ist auch das App Secret einzusetzen (Bild 4). Sie finden es im App Center in den Settings über die unscheinbaren drei Punkte am oberen rechten Seitenrand hinter der Funktion Copy app secret. Damit befindet sich der Schlüssel in der Zwischenablage und kann komfortabel im Code eingefügt werden. Ignorieren Sie für den Moment einfach den Hinweis von Microsoft, das nicht zu tun, und schmunzeln Sie darüber, dass nirgends erläutert wird, mit was für Konsequenzen man alternativ rechnen könnte.

Das App-Center-Secret(Bild 4)
Autor
Wichtig: In entsprechenden Beispielen von Microsoft wird das Thema App Secret immer so oder so ähnlich dargestellt:
<span class="hljs-type">AppCenter</span>.<span class="hljs-type">Start</span>(
<span class="hljs-string">"ios={Your App secret here};"</span> +
<span class="hljs-string">"uwp={Your UWP App secret here};"</span> +
<span class="hljs-string">"android={Your Android App secret here};"</span> +
<span class="hljs-string">"macos={Your macOS App secret here};"</span>,
typeof(<span class="hljs-type">Analytics</span>), typeof(<span class="hljs-type">Crashes</span>))
Die geschweiften Klammern werden aber nicht übernommen. Fügen Sie das App Secret einfach direkt und ohne geschweifte Klammern in Ihren Code ein – wie es in Listing 1 zu sehen ist.An dieser Methode ist auch zu erkennen, dass sich die verschiedenen Apps einheitlich initialisieren lassen – beispielsweise iOS und Android – und Sie zugleich angeben können, welche App-Center-Features exakt genutzt werden sollen (hier Analytics und Crashes). Die NuGet-Pakete nennen sich Microsoft.AppCenter.Analytics und Microsoft.AppCenter.Crashes. Die Typen, die bei der Initialisierung angegeben werden, heißen analog dazu ebenfalls Analytics und Crashes. Während Analyse-Metriken dann auf Appcenter.ms im Bereich Analytics angezeigt werden, finden sich die Metriken aus dem Crash-Reporting wiederum unterhalb von Diagnostics. Das ergibt Sinn, kann aber am Anfang verwirrend sein.
Level 3: Daten sammeln
Nachdem nun die NuGet-Pakete installiert und das App Center SDK gestartet wurde, können Sie testweise die ersten Daten zur Analyse an das App Center schicken. Auf der Basis der .NET-MAUI-Standard-Vorlage in einer Variante, die MVVM nutzt, kann die Klasse MainViewModel zum Beispiel aussehen wie in Listing 2. Warum das keine gute Idee ist, zeigt sich gleich. Funktionieren wird der Code allerdings tadellos.Listing 2: Analysedaten senden
<span class="hljs-keyword">public</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MainViewModel</span> : <span class="hljs-title">BaseViewModel</span> <br/>{ <br/> [ObservableProperty] <br/> <span class="hljs-keyword">string</span> counterBtnText = <span class="hljs-string">"Click me!"</span>; <br/><br/> [RelayCommand] <br/> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CounterClicked</span>(<span class="hljs-params"></span>) </span><br/><span class="hljs-function"> </span>{ <br/> count++; <br/><br/> Analytics.TrackEvent(<br/> <span class="hljs-string">$"Counter clicked <span class="hljs-subst">{count}</span> times on MainPage"</span>); <br/><br/> <span class="hljs-keyword">if</span> (count == <span class="hljs-number">1</span>) <br/> CounterBtnText = <span class="hljs-string">$"Clicked <span class="hljs-subst">{count}</span> time"</span>; <br/> <span class="hljs-keyword">else</span> <br/> CounterBtnText = <span class="hljs-string">$"Clicked <span class="hljs-subst">{count}</span> times"</span>; <br/><br/> SemanticScreenReader.Announce(CounterBtnText); <br/> } <br/><br/> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>; <br/>}
In Visual Studio App Center sind nach Starten der App und Tippen auf den Button Click Me nach kurzer Zeit sowohl unter Analytics | Log flow wie auch Analytics | Events die ersten eigehenden Daten zu sehen. Im Log flow werden die einzelnen Datenpakete wirklich nahezu in Echtzeit angezeigt, was zum Beispiel dabei hilfreich ist, eine Nutzungssession zu analysieren. Unter dem Menüpunkt Events werden die eingehenden Daten wiederum aggregiert. Und dabei wird dann auch deutlich, warum die Idee, Werte direkt im Meldungstext zu parametrisieren, nicht gut ist (Bild 5): Statt dass das Click-Event in seinem Auftreten aggregiert wird, taucht es nun jedes Mal als eigenständiges Vorkommen auf. Kunststück: Es ist ja auch jedes Mal eine andere Meldung. Auch ist eine Zuordnung so kaum noch möglich, sobald mehrere Nutzer die App gleichzeitig verwenden. Die folgende Codezeile sollte daher geändert werden:

Wenig nützlicheAuswertung(Bild 5)
Autor
Analytics.TrackEvent(
$<span class="hljs-string">"Counter clicked {count} times on MainPage"</span>);
// <span class="hljs-keyword">In</span> etwas, das sich mehr wie folgt liest:
Analytics.TrackEvent($<span class="hljs-string">"Counter clicked on MainPage"</span>);
Dass es auch möglich ist, benutzerdefinierte Events mit eigenen Eigenschaften zu tracken, sollte selbstverständlich sein. Mehr darüber findet sich in der Dokumentation unter [3].
Diagnostics
Der Vollständigkeit halber sei an dieser Stelle kurz gezeigt, wie analog zu Analyse-Informationen auch Daten zu Fehlern und Abstürzen protokolliert werden können. Zum Testen dieser Möglichkeit sieht das App Center SDK direkt vor, einfach einen Test-Crash zu erzeugen, und das geht so:
Crashes.GenerateTestCrash()<span class="hljs-comment">; </span>
Hier gilt es nun Folgendes zu beachten: Aufgrund des Absturzes kann die App an dieser Stelle natürlich keine Daten mehr verschicken. Allerdings gilt hier das Gleiche wie grundsätzlich bei der Verwendung von Visual Studio App Center im Falle eines Verbindungsabbruchs: Das SDK sieht eine Datenmenge von maximal zehn MByte vor, die offline vorgehalten und im Zweifelsfall beim nächsten Start der App übertragen wird.Ein nettes Gimmick: Zur Laufzeit der Applikation lässt sich ermitteln, ob es bei letzten Verwendung zu einem Absturz kam. Microsoft weist darauf hin, dass Sie diese Information dazu nutzen können, um sich beispielsweise bei Ihren Benutzern zu entschuldigen.
Level 4: Security
Nachdem nun grundsätzlich klar ist, wie einfach Sie das App Center SDK in Ihre .NET-MAUI-App integrieren können, folgt nun das nächste Thema: Securing the App Secret. Während es natürlich auch andere Wege gibt, die zum Ziel führen, ist es zunächst einmal wichtig, eben dieses Ziel genauer zu beschreiben:- App Secrets stehen nicht im Code.
- App Secrets werden während eines CI-Builds integriert.
- App Secrets sind sicher vor dem Zugriff durch Dritte geschützt.
- Entwickler können dennoch lokal arbeiten.
Mobile.BuildTools
Zunächst einmal ist es wichtig, App Secrets vom eigentlichen Code zu entkoppeln, es dabei aber grundsätzlich auch möglich zu machen, sie durch Build-Prozesse zu reintegrieren. Mit eine der pfiffigsten Möglichkeiten hierzu ist die Nutzung der Mobile.BuildTools von Dan Siegel [4]. Und obwohl die Lösung extrem gut funktioniert, ist die initiale Einrichtung nicht ganz trivial. Auch die offizielle Dokumentation ist zwar sehr umfangreich; dennoch darf man sich die erforderlichen Schritte zunächst einmal sehr langwierig zusammensuchen – es sei denn natürlich, man kennt die hier vorliegende Einführung. Hier die Zusammenfassung.Zunächst einmal installieren Sie die aktuellste Version der Mobile.BuildTools wie üblich über den NuGet-Paketmanager. Sie benötigen das Paket Mobile.BuildTools. Im November 2022 war die Version 2.0.245 aktuell. Im Anschluss müssen die Mobile.BuildTools konfiguriert werden. Dabei kann es zwischendurch zu ein paar Fehlermeldungen kommen. Das liegt unter anderem daran, dass die Tools ähnlich wie das MVVM Toolkit von Microsoft in den tatsächlichen Build-Prozess eingreifen und dabei Code generieren.Im ersten Schritt legen Sie auf der Ebene der Solution-Datei eine Konfigurationsdatei mit dem Namen buildtools.json an. Und obwohl die Build Tools über ein reichhaltiges Repertoire an Features verfügen, interessiert im Moment nur der Abschnitt für die AppSettings.Der Inhalt reduziert sich daher zunächst einmal auf den Bereich, der die Anwendungseinstellungen beschreibt:
{
<span class="hljs-attr">"$schema"</span>:
<span class="hljs-string">"https://mobilebuildtools.com/schemas/v2/build </span>
<span class="hljs-string"> tools.schema.json"</span>,
<span class="hljs-attr">"appSettings"</span>: {
<span class="hljs-attr">"SLAYRadio.App"</span>: [
{
<span class="hljs-attr">"accessibility"</span>: <span class="hljs-string">"Public"</span>,
<span class="hljs-attr">"className"</span>: <span class="hljs-string">"AppSettings"</span>,
<span class="hljs-attr">"properties"</span>: [
{
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"AppCenteriOSSecret"</span>,
<span class="hljs-attr">"type"</span>: <span class="hljs-string">"String"</span>,
<span class="hljs-attr">"defaultValue"</span>: <span class="hljs-string">"null"</span>
},
{
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"AppCenterAndroidSecret"</span>,
<span class="hljs-attr">"type"</span>: <span class="hljs-string">"String"</span>,
<span class="hljs-attr">"defaultValue"</span>: <span class="hljs-string">"null"</span>
}
]
}
]
}
}
Wichtig hierbei ist, dass Sie den korrekten Root-Namespace angegeben. Im Beispiel oben handelt es sich um den Namespace SLAYRadio.App. Der Klassenname bestimmt den Namen der Klasse, die generiert wird, und darüber hinaus ist noch der Hinweis wichtig, dass die Mobile.BuildTools die erzeugte Klasse per Default in einem Sub-Namespace namens Helpers unterhalb des Root-Namespaces anlegen (über den Schlüssel Namespace kann dieser Name aber auch angepasst werden).Das passiert bei jedem Kompilieren erneut. Eine auf diese Weise erzeugte Klasse AppSettings kann dann aussehen wie in Listing 3.
Listing 3: Von Mobile.BuildTools generierte AppSettings
<span class="hljs-keyword">using</span> System; <br/><span class="hljs-keyword">using</span> GeneratedCodeAttribute = <br/> System.CodeDom.Compiler.GeneratedCodeAttribute; <br/><span class="hljs-keyword">namespace</span> <span class="hljs-title">SLAYRadio.App.Helpers</span> <br/>{ <br/> [GeneratedCodeAttribute(<br/> <span class="hljs-string">"Mobile.BuildTools.Generators.Secrets.</span><br/><span class="hljs-string"> SecretsClassGenerator"</span>, <span class="hljs-string">"2.0.245+55c6f25b64"</span>)] <br/> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AppSettings</span> <br/> { <br/> [GeneratedCodeAttribute(<br/> <span class="hljs-string">"Mobile.BuildTools.Generators.Secrets.</span><br/><span class="hljs-string"> SecretsClassGenerator"</span>, <span class="hljs-string">"2.0.245+55c6f25b64"</span>)] <br/> <span class="hljs-keyword">public</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> AppCenteriOSSecret = <span class="hljs-keyword">default</span>; <br/><br/> [GeneratedCodeAttribute(<br/> <span class="hljs-string">"Mobile.BuildTools.Generators.Secrets.</span><br/><span class="hljs-string"> SecretsClassGenerator"</span>, <span class="hljs-string">"2.0.245+55c6f25b64"</span>)] <br/> <span class="hljs-keyword">public</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> AppCenterAndroidSecret = <br/> <span class="hljs-keyword">default</span>; <br/> } <br/>}
Nach einem erfolgreichen Build-Prozess finden Sie die generierte Klasse in der Datei AppSettings.g.cs zum Beispiel im Verzeichnis …\obj\Debug\net6.0-ios\ios-arm64\Helpers (je nach gewählter Plattform).Falls Sie das zu diesem Zeitpunkt dieser Einführung bereits ausprobieren, erhalten Sie vermutlich einige seltsam anmutende Fehlermeldungen. Die haben etwas damit zu tun, dass es zurzeit eine bekannte Schwierigkeit mit der Build-Reihenfolge gibt. Denn zum einen müssen die Mobile.BuildTools die Settings einlesen, dann die AppSettings-Klasse erzeugen, diese einbinden und dann den Rest des eigentlichen App-Codes übersetzen.Der aktuell bekannte Workaround besteht darin, die Datei .csproj um einen Eintrag zu ergänzen, der die Reihenfolge korrigiert:
<span class="hljs-tag"><<span class="hljs-name">Target</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"MBTHack"</span> <span class="hljs-attr">BeforeTargets</span>=<span class="hljs-string">"Secrets"</span> </span>
<span class="hljs-tag"> <span class="hljs-attr">DependsOnTargets</span>=<span class="hljs-string">"MobileBuildToolsInit"</span> /></span>
Im Anschluss sollte der Build-Prozess problemlos durchlaufen und im obj-Verzeichnis die generierte Klasse auftauchen. Im Code steht allerdings noch immer kein App Secret.An dieser Stelle wirkt die Magie der Mobile.BuildTools. Denn deren Code kennt verschiedene Möglichkeiten, an die gewünschten Informationen heranzukommen. Dazu wird zunächst einmal geprüft, ob es zu den Properties passende Umgebungsvariablen gibt. Diese müssen einem vorgegebenen Namensschema folgen. Genauer: Es wird ein Präfix benötigt, per Default heißt es BuildTools_, über den Schalter Prefix lässt es sich aber auch umbenennen.Ist in der Konfigurationsdatei beispielsweise eine Property mit dem Namen AppCenteriOSSecret angegeben, so legen Sie einfach eine Systemvariable mit dem Namen BuildTools_AppCenteriOSSecret an, und als Wert hinterlegen Sie das App Secret aus den App-Center-Settings (Bild 4).Unter Umständen müssen Sie danach Visual Studio einmalig neu starten. Wird die Solution im Anschluss neu gebaut, taucht erneut eine generierte AppSettings.g.cs-Datei im obj-Verzeichnis auf. Nur dieses Mal befindet sich das App Secret darin.
Zugriff auf die App Secrets
Im nächsten Schritt geht es darum, auf diese Daten zuzugreifen. Und da es durchaus gewollt sein kann, eine solche Umgebungsvariable nicht zu setzen – was am Ende des Tages darauf hinausläuft, dass das App Center SDK für die entsprechende Plattform nicht gestartet wird –, ist es eine gute Idee, einen Wrapper drumherum zu setzen. Um das Schema zu wahren, empfiehlt sich beispielsweise ein neues Unterverzeichnis mit dem Namen Helpers und darin eine statische Klasse mit einer statischen Property, die den Zugriff auf die generierten AppSettings umgibt. Das Ergebnis kann aussehen wie in Listing 4.Listing 4: Wrapper für den Zugriff auf die AppSettings
namespace SLAYRadio.App.Helpers; <br/><br/>public static class AppConstants <br/>{ <br/> public static string AppCenterStart <br/> { <br/> get <br/> { <br/> string startup = string.Empty; <br/><br/> if (Guid.TryParse(<br/> SLAYRadio.App.Helpers.AppSettings.<br/> AppCenteriOSSecret, out Guid iOSSecret)) <br/> { <br/> startup += $"ios={iOSSecret};"; <br/> } <br/><br/> if (Guid.TryParse(<br/> SLAYRadio.App.Helpers.AppSettings.<br/> AppCenterAndroidSecret, <br/> out Guid AndroidSecret)) <br/> { <br/> startup += $"android={AndroidSecret};"; <br/> } <br/> return startup; <br/> } <br/> } <br/>}
Darin ist zu erkennen, dass mittels TryParse geprüft wird, ob etwas Verwertbares aus den AppSettings gezogen werden kann. Und falls ja, baut sich hier eine Property auf mit der Syntax, die für das Starten des App Center SDK erforderlich ist.Nachdem der Helpers-Namespace ebenfalls in der Datei GlobalUsings.cs referenziert wurde, kann abschließend das SDK in CreateMauiApp() initialisiert werden. Der Aufruf wird entsprechend leicht abgeändert:
if(!string.IsNullOrWhiteSpace(
AppConstants.AppCenterStart))
{
AppCenter.Start(AppConstants.AppCenterStart,
typeof(Analytics), typeof(Crashes));
}
Level 5: User Consent
Bevor es direkt weitergeht mit der Frage, wie Sie das alles nun in den CI-Prozess integrieren können, lohnt sich der Hinweis auf das „Lieblingsthema“ aller Softwareentwickler: die Datenschutzgrundverordnung (DSGVO).Sobald eine Anwendung Daten verschickt, müssen die Benutzer darüber in Kenntnis gesetzt werden. Diesem Thema begegnen Sie seit einiger Zeit schon täglich auf allen Webseiten, die Sie besuchen. Für Ihre Apps gibt es dabei keine Ausnahme.Es kann durchaus eine gute Strategie sein, alle Themen einzeln abzufragen (Analytics, Diagnostics). Denn zumindest der automatischen Übermittlung von Abstürzen stimmen viele Benutzer oft eher zu als dem Messen des eigenen Nutzungsverhaltens. Egal wie das Ergebnis aussieht: Eine Möglichkeit, damit umzugehen, ist, beim Starten des App Center SDK die dann gespeicherten Wünsche des Benutzers umzusetzen. Ein einfacher Weg wäre die Anpassung des Start-Codes wie folgt:
var startServices = new List<Type>();
if (Preferences.Get("ConsentAnalytics", false))
startServices.Add(typeof(Analytics));
if (Preferences.Get("ConsentDiagnostics", false))
startServices.Add(typeof(Crashes));
AppCenter.Start(
AppConstants.AppCenterStart,
startServices.ToArray());
Dieses Beispiel setzt voraus, dass es entsprechende Einstellungen gibt, die unter den oben genannte Bezeichnungen abgerufen werden können. Normalerweise würden Sie dem Benutzer dazu in den Settings der App passende Schalter zum Umlegen anbieten.Sobald sich diese Einstellungen zur Laufzeit verändern, ist eine Eigenart des SDK zu berücksichtigen. Unter Umständen kann dadurch nämlich eine Neu-Initialisierung erforderlich sein. Mehr Informationen dazu finden Sie in der offiziellen Dokumentation [3]. Faszinierend: Beinahe schon ungewöhnlich für Microsoft finden Sie in der Dokumentation zu App Center auch einen kompletten und sehr ausführlichen Abschnitt zum Thema der Datenschutzbestimmungen. Auf Englisch unter dem Begriff GDPR (General Data Protection Regulation), ist es in Deutschland unter dem Begriff DSGVO bekannt. Microsoft erläutert unter anderem sogar die Nutzung extra hierfür bereitgestellter Endpoints, um Nutzerdaten zu löschen oder zu exportieren.
Kurzes Recap
Die App-Center-Historie ist geklärt. Sie haben eine App in App Center angelegt, das SDK in Ihrer .NET-MAUI-App installiert, das App Secret in eine Umgebungsvariable ausgelagert, mit Mobile.BuildTools dafür gesorgt, dass es zur Laufzeit in den Code integriert wird, das SDK gestartet und erste Analyse-Daten an Ihre App-Center-Instanz geschickt.Um den Roundtrip zu komplettieren, gibt es jetzt noch die Integration in Azure DevOps und damit eine kurze Einführung in das Thema Continuous Integration. Gehört das in einen Einführungsartikel zum Thema Crashlytics? Nun, Microsoft hat schließlich gesagt: „[…] and integrate it into your application using your CI tools.“ Also los.Level 6: Azure DevOps
Um den Umfang dieses Artikels nicht gänzlich zu sprengen, müssen ab hier leider ein paar Abkürzungen in Kauf genommen werden, siehe Kasten Continuous Integration. Dazu werden ein paar Vorannahmen getroffen. Diese sind:Continuous Integration
Das Thema CI bedeutet unter anderem, dass die App auf einem Build-Server beispielsweise auf Grundlage eines Pushs automatisiert neu gebaut wird mit dem Ziel, das Ergebnis im Anschluss verteilen zu können (Stichwort: Continuous Deployment).
- Für Ihre .NET-MAUI-App existiert ein Azure DevOps-Projekt.
- Das DevOps-Projekt enthält ein Repository und eine Build-Pipeline, die in der Lage ist, Ihre App in Azure zu bauen.
Hinterlegen des App Secrets
Während des Build-Prozesses benötigt Azure DevOps den Zugriff auf das App Secret. Dieses wird einfach als Variable bereitgestellt. Dazu legen Sie im ersten Schritt eine neue Variablen-Gruppe an; zum Beispiel mit dem Namen AppSettings (Bild 6). In dieser Gruppe konfigurieren Sie im Anschluss eine neue Variable mit dem Namen AppCenteriOSSecret und hinterlegen als Wert das entsprechende App Secret aus Visual Studio App Center. Es ist auch möglich – und empfohlen –, das App Secret per Klick auf das kleine Schloss-Icon zu verschlüsseln.
Die neue Variablen-GruppeAppSettings anlegen(Bild 6)
Autor
An dieser Stelle ist es wichtig zu verstehen, dass die Mobile.BuildTools in verschiedenen Umgebungen die erforderlichen Daten auf unterschiedliche Weise einsammeln. Weiter oben haben Sie herausgefunden, wie Sie Umgebungsvariablen nach einem bestimmten Namensschema anlegen, damit die Mobile.BuildTools während des lokalen Build-Prozesses die App Secrets korrekt ermitteln und in den Code mittels generierter Klassen injizieren können. Das Namensschema kann dabei sogar konfigurativ angepasst werden.In der CI-Umgebung ist das etwas anders. Zu erkennen ist das im EnvironmentAnalyzervon Mobile.BuildTools. Die Methode GetPlatformSecretPrefix gibt an dieser Stelle die erwarteten Präfixe aus. Schauen Sie sich den Code gerne einmal im Repository Mobile.BuildTools auf GitHub an [5].Für Android ist das beispielsweise DroidSecret_ und für iOS iOSSecret_. An das Präfix wird dann einfach der Name der Variablen angehängt, so wie Sie ihn in der Konfiguration buildtools.json hinterlegt haben, also zum Beispiel:
iOSSecret_AppCenteriOSSecret
Damit die Build-Pipeline diese Variable setzen und mit dem Wert aus der zuvor konfigurierten Variablengruppe befüllen kann, muss sie um eine neue Variable ergänzt werden:
Variables:
group: 'AppSettings'
name: iOSSecret_AppCenteriOSSecret
value: $(AppCenteriOSSecret)
Das war es fast schon. Denn obwohl es an dieser Stelle möglich ist, die .NET-MAUI-App in Azure DevOps zu bauen und dabei das App Secret automatisiert über eine sicher hinterlegte Variable injizieren zu lassen, fehlt noch eine Kleinigkeit. Denn wo wäre der Spaß, wenn das Ergebnis nicht auch wieder im App Center auftauchen würde?
Endboss: Closing the Loop
Damit Azure DevOps im Anschluss an einen erfolgreichen Build die fertigen Artefakte in Ihre App-Center-Instanz pushen kann, sind nur wenige Konfigurationsschritte erforderlich. Versprochen.Zunächst einmal benötigen Sie ein App-API-Token für Azure DevOps, mittels dessen es sich gegenüber App Center authentifizieren kann. Dieses Token wird in App Center über die Projekteinstellungen generiert mit Settings | App API tokens | New API token. Hier vergeben Sie einfach einen Namen, der Ihnen in der Zukunft idealerweise eine Idee davon vermittelt, wozu das Token genutzt wird, und geben ihm Full Access, siehe Bild 7.
Ein neues API-Tokenhinzufügen(Bild 7)
Autor
Wichtig: Das Token wird nur jetzt gezeigt und ist danach nie wieder sichtbar. Es könnte interessant sein, es beispielsweise in einem geeigneten Passwort-Tool zu hinterlegen. Im Anschluss erstellen Sie in Azure DevOps innerhalb der Projekt-Konfiguration eine neue Service Connection. Weiter unten in der entsprechenden Auswahl möglicher Ziele findet sich der Eintrag Visual Studio App Center. Der Server-URL ist bereits vorausgefüllt. An dieser Stelle ergänzen Sie dann das zuvor generierte API-Token, geben auch der Connection einen sprechenden Namen, gewähren Zugriff auf alle Pipelines und speichern das Ganze ab.Abschließend benötigen Sie noch den sogenannten App Slug (siehe Kasten App Slug). Diesen erhalten Sie einfach über den URL, über den das App Center die entsprechende App verwaltet. Je nachdem, ob als App-Center-Account ein persönliches Konto genutzt wird oder ein Firmenkonto, kann sich der URL leicht unterscheiden.
App Slug
Unter einem Slug versteht man in diesem Kontext den Teil einer Webadresse, der diese einzigartig identifizierbar macht. In Bezug auf Visual Studio App Center handelt es sich bei dem App Slug um den Teil des URL, über den die für die jeweilige Plattform konfigurierte App identifiziert werden kann.
Sind nun der Name der neu erstellten Service Connection in DevOps und der App Slug aus dem App Center bekannt, können Sie endlich die Build Pipeline erweitern:
- task: AppCenterDistribute@3
inputs:
serverEndpoint: 'App Center Integration for
SLAYRadio.App for iOS'
appSlug: 'Blue-Sky-Innovations-GmbH/SLAYRadioApp'
appFile: '$(Build.ArtifactStagingDirectory)/**/*.ipa'
destinationType: 'groups'
releaseNotesOption: 'input'
releaseNotesInput: 'New Release'
Es empfiehlt sich an dieser Stelle auch, sich die Optionen für diesen Task näher anzuschauen, da unter anderem auch Release Notes in Form einer im Release enthaltenen und idealerweise automatisch generierten Datei übermittelt werden können. Übrigens sind die Mobile.BuildTools in der Lage, Release Notes aus Git-Commits automatisch zu erzeugen. Ansonsten muss natürlich auch der Wert für die Property appFile auf das erzeugte Artefakt verweisen.Sobald auch dieser Schritt erfolgreich abgeschlossen ist und beim Build-Prozess alle Tasks mit einem grünen Häkchen quittiert werden, taucht der neue Release im App Center im Bereich Distribute auf. Von dort aus können Sie ihn herunterladen, direkt auf einem entsprechend konfigurierten Endgerät installieren oder aber im App Store beziehungsweise dem Play Store veröffentlichen.
Fazit
Obwohl es aktuell noch nicht wieder möglich ist, mittels Visual Studio App Center eine .NET-MAUI-Applikation zu bauen, funktioniert dessen Nutzung zu Analyse- und Diagnosezwecken sehr gut, und auch die Integration ist sehr einfach.Da es bei bestehender Build-Pipeline in Azure DevOps auch sehr einfach ist, die Build-Artefakte ins App Center zu übertragen – tatsächlich wird dieser Weg von den meisten Entwicklern auch für Plattformen bevorzugt, die von App Center unterstützt werden –, gelingt auch das Deployment in die jeweiligen Stores oder von App Center aus direkt auf ein dafür konfiguriertes Endgerät sehr komfortabel.Die Konfiguration für eine sichere Verwendung der App Secrets erscheint zunächst ein wenig komplex. Dafür existiert mit den Mobile.BuildTools aber ein Werkzeug, das Sie dabei (und auch bei diversen anderen Themen) sinnvoll unterstützt.Falls Sie sich also in der Microsoft-Welt zu Hause fühlen und bisher noch keine Erfahrungen mit Crashlytics-Werkzeugen von Drittanbietern gemacht haben, dann sei Ihnen Visual Studio App Center auch für .NET MAUI Apps wärmstens empfohlen.Fussnoten
- Visual Studio App Center, https://appcenter.ms
- MAUI App Accelerator, http://www.dotnetpro.de/SL2302MSAppCenter1
- Landingpage der Mobile.BuildTools von Dan Siegel, https://mobilebuildtools.com
- App Center Analytics Dokumentation, http://www.dotnetpro.de/SL2302MSAppCenter2
- GitHub Repository zu Mobile.BuildTools, http://www.dotnetpro.de/SL2302MSAppCenter3