30.01.2015, 17:00 Uhr
Cross Plattform Entwicklung mit Xamarin und C#
Durch die Tools von Xamarin ist es dem .NET-Entwickler möglich, in fremde Territorien einzudringen, ohne sich dabei in neue Sprachen einarbeiten zu müssen. Der Artikel gibt einen Überblick über Xamarin-Project.
Das wahrscheinlich größte Problem bei der Entwicklung von mobilen Apps ist, dass diese meistens spezifisch für eine Plattform entwickelt werden müssen. Das bedeutet, dass man im Zweifel die identische Anwendung für die drei wichtigsten Plattformen (Android, iOS und Windows Phone) entwickeln und sich zusätzlich noch in die jeweiligen Unterschiede und Besonderheiten der Plattformen einarbeiten muss. Insbesondere .NET-Entwickler haben es hier schwer: Der Marktanteil für Windows Phone liegt im niedrigen einstelligen Bereich. Apps für Windows Phone erreichen daher einen Großteil der Benutzer nicht.
Eine mögliche Alternative ist, bei der App-Entwicklung auf einen gemeinsamen Standard zu setzen, d.h. auf einen Standard, der auf allen Plattformen verfügbar ist. HTML5 wäre eine Möglichkeit. Der große Nachteil einer solchen Lösung ist allerdings, dass die Apps vom Look-and-Feel meistens nicht den Plattformen entsprechen und sich daher beim Benutzer keiner allzu großen Beliebtheit erfreuen.
Abhilfe schafft hier Xamarin-Project. Es ermöglicht, native iOS-, Mac-, Android- und Windows-Phone-Apps in C# zu entwickeln. Entwickelt wird das Projekt von der gleichnamigen Firma, die 2011 von Miguel de Icaza und Nat Friedman gegründet wurde.
Das Projekt basiert auf dem früheren Open-Source-Projekt Mono, das 2011 von Novell eingestellt wurde. Seitdem wird das Projekt von der Firma Xamarin weitergeführt. Auf der Basis von Mono hat Xamarin Erweiterungen entwickelt um Anwendungen für die einzelnen Plattformen zu erstellen.
Xamarin stellt eine kostenlose Testversion zur Verfügung. Diese ist allerdings recht stark eingeschränkt. So lässt sich beispielsweise Xamarin-Forms nicht damit verwenden. Die Business-Variante schlägt mit stolzen 999 US $ pro Jahr pro Plattform zu Buche. Bei der Entwicklung von iOS, Mac und Android sind somit drei Lizenzen für jeden Entwickler erforderlich. In der Enterprise-Variante, die noch einige Features mehr bietet, verdoppelt sich der Preis pro Plattform pro Entwickler.
Architektur
Xamarin besteht im Wesentlichen aus zwei Komponenten: Xamarin.Android (früher auch "Mono for Android") und Xamarin.iOS (früher auch MonoTouch). Beides sind Entwicklungen auf der Basis des Mono-Frameworks. Am Rande sei hier noch Xamarin.Mac erwähnt, die Komponente zum Erstellen von Anwendungen für Mac OS X. Sie unterscheidet sich leider von Xamarin.iOS doch in einigen Punkten. Die Unified API versucht die beiden SDK zu verheiraten; allerdings befindet sich diese noch in der Beta-Phase.
Die grundlegende Architektur von Xamarin ist in Abbildung 1 zu sehen. Die Entwicklung der Apps erfolgt in C# (oder in anderen .NET-Sprache) und wird dann in plattformabhängige Wrapper-Klassen umgewandelt.
Xamarin-Architektur (Bild 1)
Quelle: http://desigeek.com/blog/amit/
Die spezifischen Entwicklungen für die beiden Plattformen basieren wiederum auf den jeweiligen SDK von Google und Apple. Dadurch entsteht leider auch eine Einschränkung bei der Entwicklung für die iOS- und Mac OS-Anwendungen: Ohne Apple-Hardware geht es hier nicht weiter. Denn zum Entwickeln ist XCode, die Entwicklungsumgebung für iOS, notwendig. Diese ist allerdings nur für Mac OS X verfügbar. Ohne ein Apple-Gerät mit Mac OS X kann weder eine App kompiliert noch auf dem Gerät ausgerollt werden. Xamarin bietet die Möglichkeit einen Computer mit Mac OS X als Build-Server zu konfigurieren. So lässt sich auf dem Windows-System entwickeln. Das Mac OS X-System muss dabei per Netzwerk erreichbar sein. Dies erlaubt auch das Debuggen auf dem Windows-System. Allerdings funktioniert der Emulator zum Testen der App wiederum nur auf dem Mac OS X-System.
Bei Android existiert diese Einschränkung dagegen nicht. Das SDK für Android ist für die gängigsten Betriebssysteme verfügbar (Windows, Mac OS X und Linux).
Der Weg um eine native App für Android bzw. iOS zu erstellen unterscheidet sich je nach Plattform. Der Compile-Prozess bei Xamarin.Android läuft sehr ähnlich wie bei dem .NET Framework ab. Der Source Code wird mittels eines "Just in Time" (JIT) Compilers in "Intermediate Language" (IL) Code übersetzt. Zur Laufzeit wird dann dieser IL-Code in nativen Code kompiliert.
Bei iOS ist dagegen das Kompilieren zur Laufzeit nicht erlaubt. Daher kann JIT-Compiler verwendet werden. Xamarin verwendet hier deshalb einen AOT-Compiler (Ahead-of-Time). Bei diesem wird der komplette Code vor der Laufzeit in nativen Code übersetzt. Da der native Code vor der Laufzeit generiert wird, hat dieser gegenüber einem JIT-Compiler Performanzvorteile (insbesondere beim Starten). Allerdings führt dies auch zu kleinen Einschränkungen. Alles, was mit dem Erzeugen von Code zur Laufzeit zu tun hat, ist damit nicht möglich. Zum anderen ist eine gewisse Vorsicht im Umgang mit Generics geboten. So lassen sich beispielsweise keine Methoden mit generischen Parametern oder Rückgabewerten überschreiben oder generische Ableitung von NSObject (das Pendant zu der Klasse Object in .NET) erstellen.
IDE
Für die Entwicklung mit Xamarin lässt sich zwischen Visual Studio und Xamarin Studio als Entwicklungsumgebung wählen. Bei der Installation integriert sich Xamarin direkt als Erweiterung in Visual Studio. Mit Visual Studio lassen sich sowohl Android- als auch iOS-Apps in der für .NET-Entwickler gewohnten Entwicklungsumgebung erstellen. Zu beachten ist dabei allerdings die bereits erwähnte Einschränkung für iOS-Apps, d.h. ein Mac OS X-System muss per Netzwerk verbunden sein, um die App zu kompilieren.
Die alternative Entwicklungsumgebung ist Xamarin Studio. Xamarin Studio basiert auf der Entwicklungsumgebung des Mono-Projekts "MonoDevelop". Wer Visual Studio gewöhnt ist, wird sich auch recht schnell in Xamarin Studio zurechtfinden, da diese vom Look-and-Feel recht ähnlich aufgebaut ist. Xamarin Studio bietet neben einem Editor mit Syntax-Highlighting, Code-Completion (ähnlich wie IntelliSense) und Refactoring-Unterstützung auch direkt eine Anbindung an ein Source-Control-System (Subversion oder Git).
Um die Apps testen und vor allem Debuggen zu können, liefert Xamarin Emulatoren für die mobilen Endgeräte mit. Insbesondere für Android ist die Anzahl an möglichen Konfigurationen für die Emulatoren recht groß. Die Konfiguration umfasst dabei vor allem neben dem Gerätetyp, die Auflösung und die Android-Version bzw. das API-Level. Bei der Entwicklung der App lässt sich bestimmen, ab welchem API-Level die App lauffähig sein soll. Entsprechend muss dann auch der Emulator konfiguriert werden.
Portable Class Libraries und Shared Projects Ein wichtiges Element bei der Entwicklung von Cross-Plattform-Apps sind die Portable Class Libraries (PCL). Normalerweise werden Projekte für eine spezifische Plattform erstellt und sind dann eben auch nur für diese verwendbar. Eine normale .NET-Assembly wird beispielsweise für eine bestimmte Framework-Version kompiliert und ist dann nur mit dieser nutzbar.
Für eine plattformunabhängige Lösung ist dies aber aus naheliegenden Gründen eher unbefriedigend. Und an dieser Stelle kommen die PCL ins Spiel. Diese erlauben die Entwicklung von Komponenten, die auf verschiedenen Plattformen verwendbar sind. Dabei lässt sich eine beliebige Kombination von Ziel-Plattformen auswählen. In der aktuellen Version stehen zur Verfügung: .NET Framework 4.5, Silverlight 4, Windows Phone 7, .NET für Windows Store Apps, Xamarin.Android, Xamarin.iOS und XBox 360.
Die PCLs haben leider eine kleine Einschränkung. Aus nachvollziehbaren Gründen können keine plattformspezifischen Projekte referenziert werden. Da die PCL auf allen Plattformen verwendbar sein muss, kann diese auch nur Sachen verwenden, die auf allen Plattformen verfügbar sind - sprich nur der kleinste gemeinsame Nenner kann genutzt werden. So wird beispielsweise im Fall einer PCL für .NET, eine DLL namens ".NET Portable Subset" referenziert, die, wie der Name schon sagt, nur eine Teilmenge des kompletten .NET Framework darstellt.
Neben der PCL gibt es noch eine weitere Möglichkeit Source Code auf verschiedenen Plattformen zu verwenden: die Shared Projects (gelegentlich auch Shared Asset Projects genannt). Shared Projects werden nicht kompiliert und erzeugen dementsprechend auch keine Ausgabe in Form einer DLL oder ähnliches. Der Inhalt des Shared Projects wird automatisch in alle referenzierten Projekte kopiert und dort dann dort mitkompiliert. Die referenzierten Projekte sind dann in der Regel plattformspezifisch. Auf diese Weise lassen sich die Komponenten einmal entwickeln und dann auf allen Plattformen verwenden. Allerdings besteht auch hier eine Einschränkung: Shared Projects können keine anderen Projekte referenzieren, d.h. auch keine andern Shared Projects.
UI-Entwicklung
Eine der größten Schwierigkeiten bei der Entwicklung von Cross-Plattform-Apps ist das Entwickeln des User Interfaces (UI). Das liegt vor allem daran, dass das Look-and-Feel der App auch dem System entsprechen soll. Die Benutzeroberflächen unterscheiden sich allerdings bei den Plattformen. Zum Teil existieren verschiedene Controls, zum Teil verwenden die Plattformen verschiedene Konzepte zur Realisierung von Benutzeroberflächen. Die UI muss daher doch wieder speziell für die einzelnen Plattformen entwickelt werden. Lediglich der Code-behind kann dann wirklich plattformübergreifend verwendet werden.
Die neueste Version Xamarin 3 versucht dem mit Xamarin.Forms Abhilfe zu schaffen. Xamarin.Forms abstrahiert von der konkreten Plattform. Die UI kann daher einmal entwickelt und auf allen Plattformen verwendet werden. Im Unterschied zu anderen möglichen Lösungen wie beispielsweise HTML5 entsteht hier allerdings eine native UI, die dem Look-and-Feel der Plattform entspricht. Dies geschieht, indem die UI-Elemente zur Laufzeit in die speziellen Elemente der Plattform abgebildet werden. Abbildung 2 zeigt exemplarisch das resultierende Ergebnis auf den verschiedenen Plattformen.
Unterschiede der UI-Elemente (Bild 2)
Quelle: http://xamarin.com
Xamarin.Forms besteht im Wesentlichen aus vier Komponenten. Sie sind von der Terminologie her betrachtet zum Teil etwas gewöhnungsbedürftig:
- Pages: Sie sind die eigentlichen Seiten zum Darstellen der App. In Android stellt dies eine Activity, in iOS ein View Controller da. Es existieren fünf verschiedene Varianten: ContentPage, MasterDetailPage, NavigationPage, TabbedPage und CarouselPage
- Views: Views sind Steuerelemente wie Buttons, Labels, DatePicker oder Editor
- Layouts: Layouts sind Container-Elemente wie Grid, StackLayout oder ContentView
- Cells: Cells sind einzelne Einträge in anderen Elementen wie ListView und TableView
Xamarin.Forms ist ein großer Fortschritt bei Entwicklung von plattformunabhängigen UI. Aber man muss sich im Klaren darüber sein, dass Xamarin.Forms nur der kleinste gemeinsame Nenner der verschiedenen Plattformen sein kann. Falls dieser kleinste gemeinsame Nenner einmal nicht reicht, so besteht die Möglichkeit, einen eigenen Renderer für die jeweilige Plattform zu erstellen.
Testen einer Cross-Plattform
Ein Problem, auf das man bei der Entwicklung von mobilen Geräten fast zwangsläufig stolpert, ist das Testen auf den verschiedenen mobilen Endgeräten. Insbesondere wenn es sich um eine plattformunabhängige App handelt, ergibt sich in Kombination mit den verschiedenen Geräten und den verschiedenen Plattformen (inklusive der verschiedenen Versionen) eine recht große Anzahl an Testfällen. In der Praxis wird man oftmals nicht die Möglichkeit haben auf ausreichend vielen verschiedenen Geräten diese Tests auszuführen. Mit dem Emulator lassen sich zwar viele Testfälle abdecken, doch um einen realen Test auf dem Endgerät kommt man meistens nicht herum. Und an dieser Stelle kommt die Test Cloud von Xamarin ins Spiel.
Die Test Cloud ermöglicht es, automatisierte UI-Tests zu schreiben, die sich auf physikalischen Testgeräten ausführen lassen. Man kann die Tests entweder manuell über einen Webservice anstoßen oder die Tests, und das ist die wahrscheinlich interessantere Variante, im Zuge von Continous Integration automatisch ausführen lassen, wenn eine Änderung am Source Code vorgenommen wurde. Der Ablauf einer solchen Continous Integration ist Abbildung 3 dargestellt.
Kombination mit Continous Integration (Bild 3
)
)
Quelle: Quelle: http://developer.xamarin.com
Für das Erstellen der Tests gibt es zwei verschiedene Möglichkeiten. Die erste Variante ist das Erstellen der Tests mit dem Calabash-Framework, das Cucumber verwendet. Damit lassen sich Tests mit Ruby entwickeln, die nach dem Konzept des "Behavior Driven Development (BDD)" funktionieren. Wer doch lieber in C# bleiben möchte, greift zu der Alternative "Xamarin.UITest". Diese basiert auf dem bekannten NUnit-Framework.
Momentan lässt sich leider kein Test für Windows-Phone-Geräte erstellen sondern nur für Android- und iOS-Geräte. Ein Test-Cloud-Projekt lässt sich allerdings nur für eine einzelne Plattform erstellen. Benötigt man Tests für beide Plattformen, so muss man zwei separate Projekte erstellen.
Der Entwickler erhält die Ergebnisse der Tests per Mail. Neben den reinen Ergebnissen zeichnet die Test Cloud noch verschiedene Performance-Indikatoren (zum Beispiel Speicherverbrauch und CPU-Last) beim Test auf. Dies kann eine durchaus nette Zusatzinformation darstellen.
Xamarin bietet daneben noch eine weitere interessante Möglichkeit seine App zu testen: den "App-Explorer". Mit diesem lassen sich so genannte Tours aufzeichnen. Eine Tour beginnt mit dem Starten der App und besteht dann aus bis zu zehn Aktionen, wobei eine Aktion beispielsweise ein Button-Klick sein kann. Diese Tour wird aufgezeichnet und später wieder abgespielt. Das Ziel dieser Test ist kein vollständiger Test auf korrekte Funktionalität (dafür sind Xamarin.UITest und Calabash konzipiert). Vielmehr geht es darum eine Art Smoke-Test durchzuführen: sprich "raucht" die App beispielsweise direkt beim Starten ab? Das Resultat eines solchen Tests ist dementsprechend auch nur, ob die Tour beendet werden konnte oder nicht. Auch hier kann konfiguriert werden auf welchem Gerät die Tour gestartet werden soll.
Xamarin Components
Über den Xamarin Component Store lassen sich weitere API, UI-Komponenten oder auch Themes herunterladen. Zum Teil sind diese kostenlos, zum Teil sind sie aber auch kostenpflichtig.
Eine kleine Auswahl der interessantesten:
- Xamarin Mobile: API, die von Xamarin selbst entwickelt wurde, um den Zugriff auf plattformspezifischen Features zu erleichtern. Dazu zählen beispielsweise der Zugriff auf die Kamera, das Adressbuch oder das GPS-Modul
- JSon.net: Implementierung des JSON-Frameworks
- Google Maps: Ermöglicht das Einbinden von Google Maps in die App
- SQLite.net: Ein leichtgewichtiger SQLite Client mit ORM-Unterstützung
- Xamarin.Auth: Eine Benutzerverwaltung zum Anlegen und Authentifizieren von Benutzern.
- Azure Mobile Service: API zur Verwendung des Azure Mobile Service.
- Amazon Fire OS: Ermöglicht die Entwicklung von Apps für Amazon Fire Phone und Amazon Kindle.
Fazit
Xamarin stellt einen großen Schritt für die plattformunabhängige Entwicklung von nativen Apps mit dem .NET Framework dar. .NET-Entwicklern bietet es die Möglichkeit, Apps für die wichtigsten Systeme zu entwickeln und sich nicht nur auf das (momentan noch) nicht sehr weit verbreitete Windows Phone zu beschränken. Der Entwickler muss sich nicht in eine neue Sprache und Umgebung einarbeiten sondern kann in seiner gewohnten Visual Studio-Umgebung arbeiten und muss auch nicht auf die vielen schönen Sprach-Features wie beispielsweise Linq, die einem das .NET-Framework anbietet, verzichten.
Insbesondere Xamarin-Forms stellt gegenüber der früheren Version einen enormen Fortschritt dar. Es bietet die Chance, plattformunabhängig UI zu entwickeln, die sich dann allerdings dem Look-and-Feel der Plattform auf dem mobilen Endgerät anpasst. Allerdings bietet Xamarin.Forms nur den kleinsten gemeinsamen Nenner der UI, d.h. es werden nur die UI-Elemente unterstützt, die auch auf allen Plattformen eine Entsprechung haben. Falls das nicht ausreichend ist, so besteht die Möglichkeit bestimmte Pages für jede Plattform speziell zu entwickeln.
Xamarin befreit den Entwickler davon, die komplette App für jede Plattform gesondert zu entwickeln. Gleichwohl befreit es den Entwickler nicht, sich mit Besonderheiten und Unterschieden der einzelnen Plattformen zu beschäftigen. Komplett plattformunabhängig lassen sich daher viele Xamarin-Apps nicht entwickeln, aber die Möglichkeiten, gemeinsamen Code in Shared Projects oder PCL zu entwickeln und einen Großteil der UI mit Xamarin.Forms zu definieren, vereinfachen die Entwicklung erheblich.
Björn Dreher ist als Softwareentwickler und Berater bei der adesso AG angestellt. Er arbeitet dort in verschiedenen Projekten im Microsoft-Umfeld. Sein Schwerpunkt liegt in der Entwicklung mit C#. Er ist unter dreher@adesso.de erreichbar.