Avalonia auf mobilen Plattformen

Im Artikel „UIs für Linux“ wurde das Cross-Plattform UI-Framework Avalonia bereits im Hinblick auf die Entwicklung für Desktop-Umgebungen unter Linux vorgestellt. Dazu gab es weitere Artikel, die Avalonia im Kontext von Browser-Apps und Embedded-Apps vorgestellt haben. Dieser Artikel lenkt den Blick auf die seit Avalonia 11 unterstützten mobilen Plattformen iOS und Android.
Voraussetzungen zur Entwicklung für Android und iOS
Bevor man mit der Entwicklung von Avalonia-Apps für Android und iOS starten kann, müssen noch einige Voraussetzungen erfüllt sein. Zunächst benötigen wir die notwendigen Workloads in der lokalen .NET-Installation. Diese installieren wir wie folgt:
dotnet workload install android
dotnet workload install ios
Daneben benötigen wir je nach Plattform noch weitere Abhängigkeiten, für Android etwa das Android SDK und JDK (Java Development Kit). Eine einfache Variante zur Installation dieser Abhängigkeiten ist eine Installation der kostenlosen Entwicklungsumgebung Android Studio. Für Nutzer von Visual Studio steht zudem eine Workload im Visual Studio Installer bereit (.NET Multi-Platform App UI-Entwicklung), über die wir die notwendigen Abhängigkeiten bekommen. Bei der Auswahl des Android SDK ist zu beachten, welche Version von Android mindestens unterstützt werden soll.
Für die Entwicklung von Avalonia-Apps auf iOS wird zwangsweise ein Gerät von Apple benötigt. Zwar ist das Programmieren auch unter Windows oder Linux möglich, beim Kompilieren, Debuggen und spätestens beim Veröffentlichen der App brauchen wir macOS. Auf macOS werden die notwendigen Abhängigkeiten durch eine Installation von Xcode, der IDE von Apple, installiert.
Neben den SDKs bekommen wir auch Emulatoren (Android) und Simulatoren (iOS), mit deren Hilfe wir unsere App auf einem emulierten Gerät testen können. Wie das am Beispiel von iOS aussieht, sehen wir in Bild 1.

Es empfiehlt sich dennoch, regelmäßig auf echten Geräten zu testen, da nur hier die volle Bandbreite an Sensoren, Touch-Eingabe und weitere Faktoren wie Wärmeentwicklung oder Energieverbrauch getestet werden können.
Blick auf ein Beispielprojekt
Eine neue Avalonia-App mit Android- und iOS-Unterstützung lässt sich mit dem Template Avalonia Cross Platform Application erstellen. Mit dem Template haben wir uns bereits im vorangegangenen Artikel zu Browser-Apps beschäftigt, daher wird hier nicht näher darauf eingegangen. Für diesen Artikel sind die aus dem Template entstehenden Kopfprojekte für Android und iOS aus dem Beispielcode relevant.
In Listing 1 sehen wir den Einstiegspunkt für eine Avalonia-App unter Android.
Listing 1: Einstiegspunkt für eine Avalonia-App unter Android
[Activity(
Label = "HappyCoding.TemperatureViewer.Android",
Theme = "@style/MyTheme.NoActionBar",
Icon = "@drawable/icon",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity<App>
{
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.WithInterFont();
}
}
Eine Activity ist in kurzen Worten ein Screen einer Android-Applikation – in diesem Fall vergleichbar mit dem Hauptfenster einer Desktop-Applikation. Avalonia stellt uns die Basisklasse AvaloniaMainActivity bereit, von der wir erben können. Sie kümmert sich darum, die Avalonia-Applikation innerhalb der Activity einzubinden.
In Listing 2 sehen wir das Pendant für iOS.
Listing 2: Einstiegspunkt für eine Avalonia-App unter iOS
// Main.cs
public class Application
{
static void Main(string[] args)
{
UIApplication.Main(args, null, typeof(AppDelegate));
}
}
// AppDelegate.cs
[Register("AppDelegate")]
public partial class AppDelegate : AvaloniaAppDelegate<App>
{
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.WithInterFont();
}
}
Die Struktur ist dabei anders, das AppDelegate etwa ist so etwas wie das Root-Objekt in der iOS-Applikation. Avalonia stellt auch hier die Basisklasse AvaloniaAppDelegate bereit, die sich um die Integration der Avalonia-Applikation kümmert.
Der Rest der Avalonia-Applikation kann so umgesetzt werden, wie wir es von anderen Beispielen bereits kennen.
Unterscheidung zu .NET MAUI
Auf den ersten Blick erfüllen .NET MAUI und Avalonia den gleichen Zweck. Beide sind UI-Frameworks, die uns neben anderen Plattformen die Entwicklung auf Android und iOS ermöglichen. Der erste Blick täuscht aber, denn unter der Haube gehen beide Frameworks unterschiedliche Wege.
.NET MAUI könnte man weniger ein eigenes UI-Framework, sondern mehr eine Abstraktion vorhandener UI-Frameworks nennen. Das Framework bietet uns eine Abstraktion über die nativen UI-Frameworks von Android, iOS, macOS und Windows. Die im XAML-Code definierten Controls werden somit in native Controls übersetzt. Der klare Vorteil: Wir erhalten ein natives Look and Feel auf allen unterstützten Plattformen. Aufseiten der Nachteile erhalten wir größere Testaufwände, da sich die unterschiedenen Plattformen auch anders verhalten. Tendenziell ist auch der Funktionsumfang kleiner, da wir uns auf einer Schnittmenge über alle Plattformen bewegen.
Avalonia auf der anderen Seite rendert alle Controls selbst und ist damit eher vergleichbar mit Flutter oder Qt/QML. Hier erhalten wir das gleiche Look and Feel auf allen Plattformen. Die Vor- und Nachteile sind gegenläufig zu den vorher bezüglich .NET MAUI genannten. Features entsprechen weitgehend dem, was man von der Desktop-Plattform kennt.
Zugriff auf Geräte-Features
Avalonia beschränkt sich darauf, ein UI-Framework zu sein. Es kümmert sich somit nicht um die Anbindung von Geräte-Features auf den mobilen Plattformen. Glücklicherweise stellt Microsoft im Rahmen von .NET MAU das Paket Microsoft.Maui.Essentials bereit. Es bietet ein umfassendes API, über das verschiedenste Gerätefeatures wie Zwischenablage, Teilen-Funktion oder Vibration angesprochen werden können. Anders als der Name vermuten lässt hat Microsoft.Maui.Essentials praktisch keine Abhängigkeit zu .NET MAUI selbst.
AOT auf iOS
Bei der langen Liste von unterstützten Plattformen bringen einige davon ihre eigenen Herausforderungen mit. Bei den mobilen Plattformen stellt sich bei iOS insbesondere das Problem, dass Apple hier keinen dynamisch ausgeführten Code erlaubt. Auf iOS wird also nicht wie auf anderen Plattformen IL-Code ausgeführt, stattdessen wird dieser vorher bereits in Maschinencode übersetzt.
Zwar bringt AOT Vorteile wie schneller startende Apps. Der wesentliche Nachteil liegt aber darin, dass einige Features von .NET nicht unterstützt werden. Das betrifft etwa dynamische Codegenerierung mit Reflection.Emit. Auch wenn man solche Features selbst nicht nutzt, können Abhängigkeiten der eigenen App auf diese zugreifen und damit nicht korrekt funktionieren. Ein populäres Beispiel ist Entity Framework Core.
Fazit
Historisch hat Avalonia seine größte Stärke am Desktop. Die Unterstützung für die mobilen Plattformen Android und iOS ist erst in Version 11 am 7. Juli 2023 veröffentlicht worden. Entscheidet man sich auf diesen Plattformen für Avalonia, so muss damit gerechnet werden, auf die eine oder andere Lücke zu stoßen, die man selbst oder durch ein anderes Community-Projekt ausfüllen muss. Das Potenzial, das Avalonia auf mobilen Plattformen hat, kann man aber mit einem Blick auf Flutter erkennen. Flutter ist von seiner Architektur her sehr ähnlich zu Avalonia und ist insbesondere für Cross-Plattform-Applikationen für mobile Geräte ein sehr beliebtes UI-Framework außerhalb der .NET-Welt. Man darf also gespannt sein, wie sich diese Variante für mobile Applikationen in .NET weiterentwickelt.