Dans cet article, nous allons présenter Xamarin, un outil en C# .NET permettant de faire du cross-platform sur mobile. Nous ferons un zoom plus important sur ce qu’il nous manquait : la réutilisation de librairies natives.
Avant tout Xamarin est à la fois un produit mais aussi une société. Le produit permet de répondre à une problématique très courante qui est le développement cross-platform de manière unifiée.
En effet, Xamarin, permet de créer des applications natives sur les plateformes iOS, Android et Windows Phone. L’avantage de Xamarin réside en la réutilisation et le partage du code, réduisant le time to market.
Xamarin fourni aussi son propre environnement de développement Xamarin Studio.
Ce qu’il faut bien comprendre avec Xamarin, c’est le fait que les applications sont exécutées en natif. Toutes les APIS iOS ou Android sont disponibles via du code C#. Ceci est valable aussi donc pour les pushs, l’intégration des contacts, Bluetooth…
Aujourd’hui, il y a deux manières de construire un projet Xamarin.
C’est dans cette Portable Class Library (librairie basée sur un sous-ensemble restreint de fonctionnalités .Net) que nous auront un maximum de code réutilisable. Dans cette librairie, nous mettrons nos « Models », notre couche d’accès aux services, … Depuis 2014, Xamarin supporte le pattern MVVM, bien connu des développeurs d’applications riches ou Modern avec du XAML. De fait, les ViewModels et Models pourront être partageables dans cette librairie commune. Pour plus d'informations sur le sujet, la documentation Xamarin est assez complète : http://developer.xamarin.com/guides/cross-platform/application_fundamentals/pcl/introduction_to_portable_class_libraries
Dans un projet Shared Project, nous pouvons partager du code tout en y injectant des spécificités propres à la plateforme cible. Dans un Shared Project, chaque fichier est copié à la compilation dans les sous-projets (iOS, Android, Window Phone), et c'est grâce à des directives de compilations que l'on va pouvoir exécuter du code spécifique à chacune des plateformes. Il est aussi possible de partager des vues, Xamarin.Form s'appuie sur ce type de projet pour créer des applications très simples et avec peu de spécificités au niveau visuel. Ce sera le cas d'applications métiers, de prototypes ou d'applications ayant une identité visuelle forte nécessitant un rendu identique quelque soit la plateforme.
Un Shared Project est donc moins contraignant qu’une Portable Class Library (PCL) car cette dernière restreint l’accès au Framework .NET suivant les cibles de la PCL.
La réponse est oui. Xamarin, il y a 1 an, a apporté une réponse pour cette problématique : les projets de Bindings. Les projets de Bindings produisent une DLL (donc utilisable en C#) qui expose les API d'une librairie native iOS ou Android.
Ce type de projet est très intéressant pour les éditeurs de frameworks, car en très peu de temps et à moindre coût, ils vont pouvoir rendre disponible leur framework natif sur la plateforme Xamarin.
Xamarin.Android propose deux façons de consommer des librairies java :
Le mécanisme du binding est implémenté en utilisant 2 mécanismes :
Voici les étapes à suivre pour binder une librairie Java :
Pour cela, le projet génère automatiquement 3 fichiers xml de configuration :
Par exemple il est possible que nous voulions ne pas rendre disponibles certaines classes contenues dans le jar. Il suffit pour cela d’ajouter une ligne dans le fichier MetaData.xml ce qui suit :
<remove-node path="/api/package[@name='com.octo.android']/class[@name='MyClass']" />
Une fois votre projet de binding configuré et compilé, il suffit de l’ajouter en tant que référence à votre projet Android Xamarin. Il y aura un certain nombre de choses faire dans le fichier MetaData.xml, notamment pour renommer les différents paramètres d'une méthode. En effet, pour une méthode Java ayant pour signature :
public static void log (string logLevel, string message)
nous aurons en sortie :
public static void Log (string p0, string p1)
Pour l'utilisateur qui va intégrer le SDK, ce n'est pas très user friendly. Pour renommer les paramètres de méthode, il faut ajouter ces lignes :
<attr path="/api/package[@name='com.octo.android']/class[@name='MyClass']/method[@name='log']/parameter[@name='p0' and @type='java.lang.String']" name="name">logLevel</attr>
<attr path="/api/package[@name='com.octo.android']/class[@name='MyClass']/method[@name='log']/parameter[@name='p1' and @type='java.lang.String']" name="name">message</attr>
Pour plus d’informations concernant le binding d’une librairie Java (.jar), vous pouvez vous reporter à la doc Xamarin : http://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/binding_a_java_library_(.jar)/
Maintenant que vous avez généré une DLL encapsulant votre Jar, il suffit de l’ajouter à votre projet Xamarin Android. Vous avez désormais accès à votre librairie Java comme si cela avait été une DLL développée en C# !
Afin de correctement consommer votre nouvelle librairie, il est évidemment nécessaire de bien lire la documentation de celle-ci afin de s’assurer que votre projet Android Xamarin puisse faire les appels correctement et que les fichiers de configurations et clés de ressources sont bien présents dans ces fichiers.
Il est nécessaire de développer ce projet sous Mac OS (ou d'en posséder un pour servir de build host, voir un peu plus bas). Pour cela, il faut au préalable installer la dernière version de XCode puis dans un second temps Xamarin pour Mac OS. L’inverse peut générer des problèmes lors de la compilation du projet.
Voici les étapes à suivre pour binder une librairie statique iOS :
Suite à l’ajout de votre librairie iOS, il peut être nécessaire de modifier le fichier *.linkWith.cs afin d’importer les dépendances de votre librairie.
Exemple : ici j’importe lsqlite3.dylib qui utilisé par ma librairie iOS.
[assembly: LinkWith ("[myLib].a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, ForceLoad = true, Frameworks = "CoreFoundation CoreGraphics CoreLocation Foundation QuartzCore UIKit", LinkerFlags = "-lsqlite3", IsCxx = true)]
Une fois les dépendances correctement importées, il faut maintenant s’attaquer aux interfaces que l’on souhaite rendre disponible dans votre nouvelle DLL. Pour cela, il faut donc se référer au .h et pour chaque interface Objective-C ajouter une interface C# au fichier ApiDefinition.cs
En partant de l'exemple d’interface suivant en Objective-C :
@interface MyClass : NSObject
+ (void)init;
- (NSString *)reverse:(NSString *)value;
- (NSString *)concat:(NSString *)a and:(NSString *)b;
+ (NSUUID *)currentId;
@property bool allOk;
@end
Le fichier ApiDefinition.cs qui mappe cette interface sera :
namespace myLib.iOS
{
[BaseType (typeof (NSObject))]
public interface MyClass
{
[Static, Export ("init")]
bool Init();
[Export ("reverse:")]
void Reverse(string value);
[Export("concat:and")]
string Contact([NullAllowed]string a, [NullAllowed]string b);
[Static, Export("currentId")]
string CurrentId { get; set; }
[Export("allOk")]
bool AllOk { get; set; }
}
}
Voici une liste d'astuces à se rappeler durant l'écriture du binding:
Pour plus d’information concernant le binding d’une librairie iOS (.a), vous pouvez vous reporter à la doc Xamarin : http://developer.xamarin.com/guides/ios/advanced_topics/binding_objective-c/binding_objc_libs/
Pour consommer votre librairie maintenant bindée, il suffit d’ajouter le projet de binding à votre projet Xamarin iOS pour accéder à tout ce que vous avez mappé manuellement dans le fichier ApiDefinition.cs.
Vous pouvez configurer un Mac afin de permettre la compilation depuis un Visual Studio sous Windows
En effet, Xamarin fourni un outil sous Mac OS permettant à un développeur sous Windows / Visual Studio de compiler un projet de binding et un projet Xamarin iOS depuis son poste de travail. Il s’appelle Xamarin.iOS Build Host. Une fois lancé, il suffit depuis le poste windows de référence l’ip du Mac et de renseigner le code PIN généré par Xamarin.iOS Build Host:
Grâce à Xamarin, les développeurs .NET habitués à Visual Studio et C# pourront créer des applications iOS (iPhone, iPad, Watch), Android (smartphone, tablette, wear) et bien entendu partager du code avec l’écosystème Microsoft (Phone, Tablette). Vous pouvez donc choisir de partir sur Xamarin pour un développement cross-platform si vos équipes connaissent déjà .NET. Cependant on ne s'invente pas développeurs Android et/ou iOS, il y aura donc un effort d'apprentissage non négligeable afin d'appréhender les spécificités de chacune des plateformes.